Java集合框架如何学习(Java集合框架学习笔记)

  • 时间:
  • 4130人关注

这是一篇关于java相关的编程问答内容,被327位程序员关注,内容涉及到java集合框架、java学习笔记、Java集合框架学习笔记等,由蓬冬莲 编辑补充,一起来看下大家的回答。

集合框架(collections framework)

首先要明确,集合代表了一组对象(和数组一样,但数组长度不能变,而集合能)。Java中的集合框架定义了一套规范,用来表示、操作集合,使具体操作与实现细节解耦。

其实说白了,可以把一个集合看成一个微型数据库,操作不外乎“增删改查”四种操作,我们在学习使用一个具体的集合类时,需要把这四个操作的时空复杂度弄清楚了,基本上就可以说掌握这个类了。

设计理念

主要理念用一句话概括就是:提供一套“小而美”的API。API需要对程序员友好,增加新功能时能让程序员们快速上手。

为了保证核心接口足够小,最顶层的接口(也就是Collection与Map接口)并不会区分该集合是否可变(mutability),是否可更改(modifiability),是否可改变大小(resizability)这些细微的差别。相反,一些操作是可选的,在实现时抛出

UnsupportedOperationException即可表示集合不支持该操作。集合的实现者必须在文档中声明那些操作是不支持的。

为了保证最顶层的核心接口足够小,它们只能包含下面情况下的方法:

基本操作,像之前说的“增删改查”

There is a compelling performance reason why an important implementation would want to override it.

此外,所有的集合类都必须能提供友好的交互操作,这包括没有继承Collection类的数组对象。因此,框架提供一套方法,让集合类与数组可以相互转化,并且可以把Map看作成集合。

两大基类Collection与Map

在集合框架的类继承体系中,最顶层有两个接口:

Collection表示一组纯数据

Map表示一组key-value对

一般继承自Collection或Map的集合类,会提供两个“标准”的构造函数:

没有参数的构造函数,创建一个空的集合类

有一个类型与基类(Collection或Map)相同的构造函数,创建一个与给定参数具有相同元素的新集合类

因为接口中不能包含构造函数,所以上面这两个构造函数的约定并不是强制性的,但是在目前的集合框架中,所有继承自Collection或Map的子类都遵循这一约定。

Collection

java-collection-hierarchy

如上图所示,Collection类主要有三个接口:

Set表示不允许有重复元素的集合(A collection that contains no duplicate elements)

List表示允许有重复元素的集合(An ordered collection(also known as a sequence))

Queue JDK1.5新增,与上面两个集合类主要是的区分在于Queue主要用于存储数据,而不是处理数据。(A collection designed for holding elements prior to processing.)

Map集合

MapClassHierarchy

Map并不是一个真正意义上的集合(are not true collections),但是这个接口提供了三种“集合视角”(collection views),使得可以像操作集合一样操作它们,具体如下:

把map的内容看作key的集合(map’s contents to be viewed as a set of keys)

把map的内容看作value的集合(map’s contents to be viewed as a collection of values)

把map的内容看作key-value映射的集合(map’s contents to be viewed as a set of key-value mappings)

以上就是码农之家java培训机构的小编针对“Java集合框架学习笔记”的内容进行的回答,希望对大家有所帮助,如有疑问,请在线咨询,有专业老师随时为你服务。

码农之家
精选回答2:Java复习之集合框架总结

10小时4分钟前回答

俗话说:温故而知新。想想学过的知识,就算是以前学得很不错,久不用了,就会忘记,所以温习一下以前学习的知识我认为是非常有必要的。而本篇文件温习的是 Java基础中的集合框架。

为什么会有集合框架?

平时我们用数组存储一些基本的数据类型,或者是引用数据类型,但是数组的长度是固定的,当添加的元素超过了数组的长度时,需要对数组进行重新的定义,这样就会显得写程序太麻烦,所以Java内部为了我们方便,就提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少。

数组可以存储基本数据类型,也可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址,而集合只能存储引用数据类型(也就是对象),其实集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象。

有了集合不意味着我们要抛弃数组,如果需要存储的元素个数是固定的,我们可以使用数组,而当存储的元素不固定,我们使用集合。

集合的种类

集合分为单列集合和双列集合。单列集合的根接口为Collection,双列结合的根接口为Map,两种集合都有基于哈希算法的集合类(HashMap和HashSet),现在我们可能会有疑问,到底是双列集合基于单列集合还是单列集合基于双列集合呢,下面我们来看往集合HashMap和HashSet添加元素的源码:

/*
*HashMap的put 方法 
*/
 public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
  }

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
          boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
      n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
      tab[i] = newNode(hash, key, value, null);
    else {
      Node<K,V> e; K k;
      if (p.hash == hash &&
        ((k = p.key) == key || (key != null && key.equals(k))))
        e = p;
      else if (p instanceof TreeNode)
        e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
      else {
        for (int binCount = 0; ; ++binCount) {
          if ((e = p.next) == null) {
            p.next = newNode(hash, key, value, null);
            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
              treeifyBin(tab, hash);
            break;
          }
          if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            break;
          p = e;
        }
      }
      if (e != null) { // existing mapping for key
        V oldValue = e.value;
        if (!onlyIfAbsent || oldValue == null)
          e.value = value;
        afterNodeAccess(e);
        return oldValue;
      }
    }
    ++modCount;
    if (++size > threshold)
      resize();
    afterNodeInsertion(evict);
    return null;
  }

/*
* HashSet 的add 方法
*/
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
  }
// PRESENT是一个Object 对象
 private static final Object PRESENT = new Object();

由上源码,我们可以看出,双列集合的put方法源码中并没有出现add方法,而单列集合的add源码只能怪出现了put;我们可以知道单列集合是基于双列集合实现的。其实道理很简单,单列集合每次添加元素,只要添加key就可以,而key也是双列集合元素的唯一标识,而其值value则由一个Object对象代替并且隐藏,每次加入,输出元素都是隐藏单列结合的这个值, 底层基于双列集合,隐藏一列是很好实现的,而如果是单列集合要变成双列集合估计就会有很大的难度,就好比魔术师变魔术,魔术师变东西前肯定事先准备好要变的东西,只是将其隐藏,但是如果魔术师变魔术是真的从无到有,那我估计他就是神仙了,想要什么就变出来什么便是。

单列集合

首先我们看单列结合的继承图,单列集合的根接口是Collection,而List的实现类为ArrayList、LinkedList、Vector,Set接口的实现类是HashSet和TreeSet。

Java复习之集合框架总结

其次我们来看看各个集合的功能

List集合的特有功能概述

    * void add(int index,E element) //集合中添加元素
    * E remove(int index) //删除集合中index位置上的元素
    * E get(int index)  //获取集合中index位置上的元素
    * E set(int index,E element) 将index位置上的元素替换成 element

Vector类特有功能

    * public void addElement(E obj)  添加元素
    * public E elementAt(int index)  //获取元素
    * public Enumeration elements()  //获取元素的枚举(迭代遍历的时候用到)

LinkedList类特有功能

    * public void addFirst(E e)及addLast(E e)  //集合头添加元素或者集合尾添加元素
    * public E getFirst()及getLast() //获取头元素 获取尾元素
    * public E removeFirst()及public E removeLast() //删除头元素删除尾元素
    * public E get(int index);//获取index元素

根据上述LinkedList的功能,我们可以模拟栈获取队列的数据结构,栈是先进后出,队列为先进先出。

/**
 * 模拟的栈对象
 * @author 毛麒添
 * 底层还是使用LinkedList实现
 * 如果实现队列只需要将出栈变为 removeFirst 
 */
public class Stack {

  private LinkedList linklist=new LinkedList();
  
  /**
   * 进栈的方法
   * @param obj
   */
  public void in(Object obj){
    linklist.addLast(obj);
  }
  
  /**
   * 出栈
   */
  public Object out(){
    return linklist.removeLast();
  }
  /**
   * 栈是否为空
   * @return
   */
  public boolean isEmpty(){
    return linklist.isEmpty();
  }
}


//集合的三种迭代(遍历集合)删除
ArrayList<String> list=new ArrayList();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("world");
//1,普通for循环删除元素
for(int i=0;i<list,size();i++){//删除元素b
   if("b".equals(list.get(i))){
    list.remove(i--);// i-- 当集合中有重复元素的时候保证要删除的重复元素被删除
 }
}
//2.使用迭代器遍历集合
Iterator<String> it=list.iterator();
while(it.hasNext){
  if("b".equals(it.next())){
   it.remove();//这里必须使用迭代器的删除方法,而不能使用集合的删除方法,否则会出现并发修改异常(ConcurrentModificationException)
 }
}

//使用增强for循环来进行删除
for (String str:list){
   if("b".equals(str)){
    list.remove("b");//增强for循环底层依赖的是迭代器,而这里删除使用的依旧是集合的删除方法,同理肯定是会出现并发修改异常(ConcurrentModificationException),所以增强for循环一直能用来遍历集合,不能对集合的元素进行删除。
 }
}

接下里我们看Set集合,我们知道Set 集合存储无序,无索引,不可以存储重复的对象;我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数,其中HashSet底层基于哈希算法,当HashSet调用add方法存储对象,先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象,如果没有哈希值相同的对象就直接存入集合,如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存。下面给出HashSet存储自定义对象的一个例子,自定义对象需要重写hashCode()和equals()方法。

/**
 * 自定义对象
 * @author 毛麒添
 * HashSet 使用的bean 重写了equals和HashCode方法
 */
public class Person1 {
  private String name;
  private int age;
  public Person1() {
    super();
    // TODO Auto-generated constructor stub
  }
  public Person1(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  @Override
  public String toString() {
    return "Person1 [name=" + name + ", age=" + age + "]";
  }
  
  //使HashSet存储元素唯一
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    System.out.println("equals调用了");
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Person1 other = (Person1) obj;
    if (age != other.age)
      return false;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    return true;
  }  
}

public class Demo1_Hashset {

  public static void main(String[] args) {
    HashSet<Person1> hs=new HashSet<Person1>();
    hs.add(new Person1("张三", 23));
    hs.add(new Person1("张三", 23));
    hs.add(new Person1("李四", 24));
    hs.add(new Person1("李四", 24));
    hs.add(new Person1("李四", 24));
    hs.add(new Person1("李四", 24));
    System.out.println(hs);
  }

运行结果如图,达到了不存储重复自定义对象的目的。其实HashSet的下面还有一个LinkedHashSet,底层是链表实现的,是set中唯一一个能保证怎么存就怎么取的集合对象,是HashSet的子类,保证元素唯一,与HashSet原理一样,这里就不多说了。

Java复习之集合框架总结

最后是TreeSet集合,该集合是用来进行排序的,同样也可以保证元素的唯一,可以指定一个顺序, 对象存入之后会按照指定的顺序排列。

指定排序有两种实现:

Comparable:集合加入自定义对象的时候,自定义对象需要实现Comparable接口,

  • 实现接口的抽象方法中返回0,则集合中只有一个元素
  • 返回正数,则集合中怎么存则怎么取,
  • 返回负数,集合倒序存储

Comparator(比较器):

  • 创建TreeSet的时候可以制定 一个Comparator
  • 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
  • add()方法内部会自动调用Comparator接口中compare()方法排序
  • 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

原理:

  • TreeSet底层二叉排序树
  • 返回小的数字存储在树的左边(负数),大的存储在右边(正数),相等则不存(等于0)
  • 在TreeSet集合中如何存取元素取决于compareTo()方法的返回值

下面来看例子:

/**
 * 自定义对象 用于TreeSet
 * @author 毛麒添
 *
 */
public class Person implements Comparable<Person>{

  private String name;
  private int age;
  
  public Person(){
    super();
  }
  public Person(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  @Override
  public String toString() {
    return "Person [name=" + name + ", age=" + age + "]";
  }
  
  @Override
  public boolean equals(Object obj) {
    Person p=(Person) obj;
    return this.name.equals(p.name)&&this.age==p.age;
  }
  
  @Override
  public int hashCode() {
    // TODO Auto-generated method stub
    return 1;
  }
  
  /*//按照年龄进行排序(TreeSet)
  @Override
  public int compareTo(Person o) {
    int number=this.age-o.age;//年龄是比较的主要条件
    //当年龄一样的时候比较名字来确定排序
    return number==0?this.name.compareTo(o.name):number;
  }*/
  
  //按照姓名进行排序(TreeSet)
    @Override
    public int compareTo(Person o) {
      int number=this.name.compareTo(o.name);//姓名是比较的主要条件
      //当姓名一样的时候比年龄来确定排序
      return number==0?this.age- o.age:number;
    }
    
    //按照姓名长度进行排序(TreeSet)
        /*@Override
        public int compareTo(Person o) {
          int length=this.name.length()-o.name.length();//姓名长度比较的次要条件
          int number=length==0?this.name.compareTo(o.name):length;//姓名是比较的次要条件
          //比年龄也是次要条件
          return number==0?this.age- o.age:number;
        }*/
}

/**
 * 
 * @author 毛麒添
 * TreeSet集合
 * 集合加入自定义对象的时候,自定义对象需要实现Comparable接口,
 * 实现接口的抽象方法中返回0,则集合中只有一个元素
 * 返回正数,则集合中怎么存则怎么取,
 * 返回负数,集合倒序存储
 * 
 * 将字符按照长度来进行排序在TreeSet中,需要使用有比较的构造方法进行比较。
 */
public class Demo_TreeSet {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    demo1();//整数存取排序
    demo2();//自定义对象排序
    
    //将字符按照长度来进行排序在TreeSet中
    TreeSet<String> strLenset=new TreeSet<String>(new compareByLen());
    strLenset.add("aaaaa");
    strLenset.add("lol");
    strLenset.add("wrc");
    strLenset.add("wc");
    strLenset.add("b");
    strLenset.add("wnnnnnnnnnnn");
    
    System.out.println(strLenset);
  }

  private static void demo2() {
    TreeSet<Person> ptreeSet=new TreeSet<Person>();
    
    ptreeSet.add(new Person("李四",12));
    ptreeSet.add(new Person("李四",16));
    ptreeSet.add(new Person("李青",16));
    ptreeSet.add(new Person("王五",19));
    ptreeSet.add(new Person("赵六",22));
    
    System.out.println(ptreeSet);
  }

  private static void demo1() {
    TreeSet< Integer> treeSet=new TreeSet<Integer>();
    treeSet.add(1);
    treeSet.add(1);
    treeSet.add(1);
    treeSet.add(3);
    treeSet.add(3);
    treeSet.add(3);
    treeSet.add(2);
    treeSet.add(2);
    treeSet.add(2);
    
    System.out.println(treeSet);
  }

}

//TreeSet 构造器,实现compare对需要存储的字符串进行比较
class compareByLen implements Comparator<String>{

  //按照字符串的长度进行比较,该方法的返回值和继承Comparable的compareTo方法返回值同理。
  @Override
  public int compare(String o1, String o2) {
    int num=o1.length()-o2.length();//以长度为主要条件
    return num==0?o1.compareTo(o2):num;//内容为次要条件
  }
  
}

下面是运行截图,其中compareTo的实现方法对几种条件排序进行了实现,具体可以查看Person自定义类中的实现。

Java复习之集合框架总结

单列集合复习就到这里吧。

双列集合

同样的,在复习双列结合之前我们先看看双列集合的继承图。

Java复习之集合框架总结

Map集合的功能梳理:

添加功能

  • V put(K key,V value):添加元素。
  • 如果键是第一次存储,就直接存储元素,返回null
  • 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

删除功能

  • void clear():移除所有的键值对元素
  • V remove(Object key):根据键删除键值对元素,并把值返回

判断功能

  • boolean containsKey(Object key):判断集合是否包含指定的键
  • boolean containsValue(Object value):判断集合是否包含指定的值
  • boolean isEmpty():判断集合是否为空

获取功能

  • Set<Map.Entry<K,V>> entrySet():
  • V get(Object key):根据键获取值
  • Set<K> keySet():获取集合中所有键的集合
  • Collection<V> values():获取集合中所有值的集合

长度功能

  • int size():返回集合中的键值对的个数

Map类集合也有三种遍历方式:

  • 使用迭代器进行遍历
  • 使用增强For循环来进行遍历
  • 使用Map.Entry来遍历集合中的元素

下面我们来看看如何实现上面三种遍历方式

/**
 * 
 * @author 毛麒添
 * Map 集合的遍历
 */
public class Demo {

  public static void main(String[] args) {
    Map<String ,Integer> map=new HashMap<String, Integer>();
    map.put("张三", 18);
    map.put("李四", 19);
    map.put("王五", 20);
    map.put("赵六", 21);
    
    //使用迭代器进行遍历
    /*Set<String> keySet = map.keySet();//获取所有key的集合
    Iterator<String> iterator = keySet.iterator();
    while(iterator.hasNext()){
      String key = iterator.next();
      Integer i=map.get(key);
      System.out.println(i);
    }*/
    //使用增强For循环来进行遍历
    for (String key :map.keySet()) {
      Integer integer = map.get(key);
      System.out.println(integer);
    }
/*---------------------------使用Map.Entry来遍历集合中的元素--------------------------*/
    Set<Map.Entry<String,Integer>> en=map.entrySet();////获取所有的键值对象的集合
    /*//使用迭代器来遍历
    Iterator<Entry<String, Integer>> iterator = en.iterator();
    while(iterator.hasNext()){
      Entry<String, Integer> e=iterator.next();//获取键值对对象
      String key = e.getKey();//根据键值对对象获取键
      Integer value = e.getValue();//根据键值对对象获取值
      System.out.print(key);
      System.out.println(value);
    }*/
    //使用增强for循环来遍历
    for (Entry<String, Integer> entry : en) {
      String key = entry.getKey();
      Integer value = entry.getValue();
      System.out.print(key);
      System.out.println(value);
    }
/*---------------------------使用Map.Entry来遍历集合中的元素--------------------------*/
  }
}

LinkHashMap与LinkHashSet一样,怎么存怎么取,保证元素唯一(key 是唯一判定值),由于保证元素唯一,其性能肯定会低一些,这里就不细说了。

TreeMap是双列集合,其实他和TreeSet是很像的,但是双列集合的键是唯一标识,所以TreeMap排序的是每个元素的键。对于存储自定义对象排序,它也有Comparable和Comparator,下面我们来看例子

/**
 * 
 * @author 毛麒添
 * TreeMap
 * 通TreeSet 原理,存取自定义对象也需要继承Comparable结构,
 * 或者实现比较器Comparator
 */
public class Demo6_TreeMap {

  public static void main(String[] args) {
    TreeMap<Student, String> tm=new TreeMap<Student, String>(new Comparator<Student>() {

      @Override
      public int compare(Student s1, Student s2) {
        int num=s1.getName().compareTo(s2.getName());//以姓名作为主要比较条件
        return num==0?s1.getAge()-s2.getAge():num;
      }
    });
    tm.put(new Student("张三",13),"杭州");
    tm.put(new Student("张三",14), "贺州");
    tm.put(new Student("王五",15), "广州");
    tm.put(new Student("赵六",16), "深圳");
    
    System.out.println(tm);
  }

}

/**
 * 自定义对象
 * @author 毛麒添
 * HashMap 存储对象 与 HashSet 同理 需要重写 hashcode 和equals 方法 
 * TreeMap 实现 Comparable接口
 */
public class Student implements Comparable<Student>{

  private int age;
  private String name;
  
  public Student(){
    super();
  }
  public Student(String name,int age){
    this.name=name;
    this.age=age;
  }
  public int getAge() {
    return age;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  
  
  @Override
  public String toString() {
    return "Student [age=" + age + ", name=" + name + "]";
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Student other = (Student) obj;
    if (age != other.age)
      return false;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    return true;
  }
  @Override
  public int compareTo(Student o) {
    int num =this.age-o.age;//以年龄为主要条件
    return num==0?this.name.compareTo(o.name):num;//姓名作为次要条件
  }  
}

到这里,Java集合框架的复习基本完成,最后来一个斗地主的例子对集合框架做一个综合应用,只是实现斗地主洗牌和发牌,至于怎么打牌,逻辑复杂,这里不做实现。

/**
 * 
 * @author 毛麒添
 * 模拟斗地主洗牌和发牌,牌排序
 * 买一副扑克
 * 洗牌
 * 发牌
 * 看牌
 */
public class Doudizhu_progress {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    //构造一副扑克牌
    String[] number={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
    String[]color={"黑桃","红桃","梅花","方块"};
    HashMap<Integer, String> pokerMap=new HashMap<Integer, String>();//存放牌的map
    ArrayList<Integer> list=new ArrayList<Integer>();//存放牌的索引
    int index=0; //索引
    for (String s1 : number) {
      for (String s2 : color) {
        pokerMap.put(index,s2.concat(s1));
        list.add(index);
        index++;
      
      }
    }
    //加入大小王
    pokerMap.put(index,"小王");
    list.add(index);
    index++;
    pokerMap.put(index,"大王");
    list.add(index);
    
    //洗牌
    Collections.shuffle(list);
    //System.out.println(list);
    
    //发牌,3个人玩 加上底牌3张 使用TreeSet 来存放索引,并自动对索引排好序
    TreeSet<Integer> mao=new TreeSet<Integer>();
    TreeSet<Integer> li=new TreeSet<Integer>();
    TreeSet<Integer> huang=new TreeSet<Integer>();
    TreeSet<Integer> dipai=new TreeSet<Integer>();
    
    for(int i=0;i<list.size();i++){
      if(i>=list.size()-3){//最后三张牌,作为底牌
        dipai.add(list.get(i)); 
      }else if(i%3==0){
        mao.add(list.get(i));
      }else if(i%3==1){
        li.add(list.get(i));
      }else {
        huang.add(list.get(i));
      }
    }
    
    //看牌
    lookPoker(pokerMap,mao,"mao");
    lookPoker(pokerMap,li,"li");
    lookPoker(pokerMap,huang,"huang");
    lookPoker(pokerMap,dipai,"底牌");
  }

  /**
   * 看牌的方法
   * @param pokerMap 存放牌的map
   * @param mao 该玩家的牌的索引集合
   * @param name 玩家名字
   */
  private static void lookPoker(HashMap<Integer, String> pokerMap,
      TreeSet<Integer> mao, String name) {
    if(name.equals("底牌")){
      System.out.print("地主"+name+"的牌是:");
    }else{
      System.out.print("玩家"+name+"的牌是:");
    }
    for (Integer integer : mao) {
      System.out.print(pokerMap.get(integer)+" ");
    }
    
    System.out.println();
    
  }

}

运行截图:

Java复习之集合框架总结

写在最后:

如果你看到这里,估计你也温故知新了吧,那就这样吧,这篇又臭又长的文章就到这里啦。希望对大家的学习有所帮助,也希望大家多多支持码农之家。

展开问题
码农之家
精选回答3:Java基础教程:Java集合框架分析

8小时59分钟前回答

二:框架分析

(0)点线框表示接口,实线框表示具体的类。

(1)常用的List、Set、Queue、Map都属于集合类。前三个都是继承自Collection,但是Map不是。

(2)List不仅可以生成普通的Iterator(因为继承自Collection),还能生成ListIterator。

(3)常用的类ArrayList、LinkedList、HashSet、HashMap。这几个类请好好研读JDK源码

(4)其它需要好好掌握的容器:CopyOnWriteArrayList、TreeSet、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap。

三:容器分析

(1)ArrayList

(1.1)底层使用一个Object数组来实现。get和set操作基于这个数组。

(1.2)List在遍历的时候,如果被修改了会抛出java.util.ConcurrentModificationException异常。

(2)LinkedList

底层采用采用一个first和last的Node<E>节点,通过链表来实现。

(3)Hashmap

(3.1)底层采用Node<K,V>[]table的数组+链表的形式来实现。

(3.2)key和value都可以为NULL。

(3.3)是线程不安全的。

(4)HashSet

底层采用HashMap来实现。

其中value使用privatestaticfinalObjectPRESENT=newObject()来表示。

(5)CopyOnWriteArrayList

(5.1)底层数据结构

finaltransientReentrantLocklock=newReentrantLock();

privatetransientvolatileObject[]array;

(5.2)基本操作

get(intindex)操作直接取数组对应的元素。

set(intindex,Eelement)操作按如下步骤:

调用lock.lock()

取index处对应的元素oldValue

如果oldValue和element不等,则复制原数组,然后设置index处的值为element,最后原数组指向新数组。

如果相等,原数组还是指向原数组。

lock.unlock()

(6)TreeMap

(6.1)继承自AbstractMap<K,V>,实现了NavigableMap<K,V>

(6.2)底层使用红黑树实现,有一个比较器来比较元素的排列顺序,元素是有序的。

(6.3)key不能为NULL,value可以为NULL。key不能为null是因为key之间需要比较大小。

(7)TreeSet

底层使用TreeMap来实现。

(8)HashTable

(8.1)put和get方法都用synchronized修饰

(8.2)底层是Entry<?,?>[]table,也是数组+链表的形式来实现。

(8.3)put操作中会检查value是否为null,是则抛出NullPointerException。put操作中会调用key.hashCode(),所以key不能为null。综上,key和value都不能为null。

(9)LinkedHashMap

(9.1)继承自HashMap,增加了一个额外的双向链表维护key插入和访问的有序性。

(9.2)内部的Entry<K,V>基础自HashMap.Node<K,V>,并增加了两个节点:Entry<K,V>before,after。

(9.3)包含LinkedHashMap.Entry<K,V>head和LinkedHashMap.Entry<K,V>tail。

(9.4)key和value都可以为null。

(10)ConcurrentHashMap

(10.1)JDK6和JDK7中采用分段锁的设计。采用segment数组和HashEntry数组的数据结构组成,segment是一种可重入锁ReentrantLock。默认segment数组大小为16。

(10.2)是否需要扩容:在插入元素之前,会判断Segment里的HashEntry数组是否超过阈值(threshold)。如果超过阀值,则需要进行扩容。而HashMap是put后才判断。

(10.3)如何扩容:ConcurrentHashMap扩容不是针对整个容器,而是针对Segment。新创建的HashEntry数组大小是原来的两倍。

(10.4)put操作步骤

为key做Hash运算,得到hash值。

通过hash值,定位到具体的Segment对象

获取可重入锁

再次通过hash值,定位到Segment中HashEntry数组的具体位置。

插入或覆盖HashEntry对象。

释放锁。

      以上就是码农之家Java培训机构小编介绍的“Java基础教程:Java集合框架分析”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。

展开问题
码农之家
精选回答4:Javase视频推荐,学习集合框架

23小时51分钟前回答

    集合框架:

    大数值计算:就好比小学的时候学习的加法运算,个位跟个位对其,十位跟十位相加,百位跟百位相加,相加时逢10进1。首先用两个集合,把组数组放入集合中,先压进去的是高位,所以高位在最下面的位置,低位最后压进去再最高(最先出站进行运算),只要满足10就进位,每出站一次运算一次。步骤:先申请2个字符串,把要计算的数值存放到字符串中,然后申请两个数组,将字符串的转换成数组,拆分进行存储。接着申请2个集合,把数组里面的数值用循环添加到集合之中(进站),这样一来高位就在下面,个位就在上面。我们先问一下2个集合那个大?按照最大的集合循环,申请一个int进位存储。最后是取值,在循环中申请2个变量,开始出站操作,每出一个转换成Integer类型,写上异常处理,如果没有值可以取出就报异常错误(分开写的用处,2个集合长度不一样)。开始计算,计算结果大于等于10整除10,就是逢10进1,不大于10不追加。最后字符串颠倒输出出去。

    集合工具类:

    排序:按照ASCII进行排序。

    混排:每次打印的结果都不一样。

    颠倒:

    搜索:搜索出来告诉下标数。

   

    拷贝:覆盖,集合进行覆盖前面的集合。

   

    最大值最小值

   

    泛型:不说明泛型就是Object类型。

    就是用来说明类型。

    在集合中非常多,用于控制集合存储类型,作用是:说明存放的是什么类型。

    <T>可以写多个

    <extendsString>这里说明类型只能是String或者String子类。

    也可以在方法上声明泛型。

    泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。

    泛型申请:

    可以在申请泛型的后面写上继承,表明继承于String,或者String下面的子类才可以,控制了范围。

    泛型要求是排序接口:

    双列集合:Map:1.Hashtble2.Hashmap双列集合有2个部分,一个存储键,一个存储值,拿值的时候要拿键来去值的。

    Map方法:

以上就是码农之家java培训机构的小编针对“Javase视频推荐,学习集合框架”的内容进行的回答,希望对大家有所帮助,如有疑问,请在线咨询,有专业老师随时为你服务。

Javase零基础学习视频

2020JavaSE进阶:http://www.xz577.com/javavideo/144.html

展开问题

参考资料

  • Offer来了:Java面试核心知识点精讲(框架篇)

    Offer来了:Java面试核心知识点精讲(框架篇)

    《 Offer来了:Java面试核心知识点精讲(框架篇) 》是对Java程序员面试中常见的微服务、网络编程、分布式存储、分布式计算等必备知识点的总结,包括Spring原理与应用、SpringCloud原理与应用、Netty网络编程原理与应用、ZooKeeper原理与应用、Kafka原理与应用、Hadoop原理与应用、HBase原理与应用、Cassandra原理与应用、ElasticSearch原理与应用、Spark原理与应用、Flink原理与应用。 这本书有11章。第一章阐述Spring的原理和应用,涉及

    大小:218 MBJava面试

    立即下载
  • JavaScript框架设计

    JavaScript框架设计

    JavaScript,框架设计

    大小:286.4 MBjs框架

    立即下载
  • Java EE框架整合开发入门到实战

    Java EE框架整合开发入门到实战

    初学者新手入门,重视实战演练教学视频,全线视频语音解读教育资源丰富 这书详细解读了JavaEE中Spring、SpringMVC和MyBatis三大框架(SSM)的基本知识和实际应用。为了方便帮助用户学习SSM框架,

    大小:232.3 MBJava EE

    立即下载
  • Java EE核心框架实战

    Java EE核心框架实战

    内容简介 《Java EE核心框架实战》旨在提高读者的学习效率,增强其项目实战能力。为此,《Java EE核心框架实战》摒弃了软件公司中不常用或不实用的技术,而是采用近200个开发案例,为读者讲解了开发商业软件的必备知识,帮组读者进行精要式的学习,汲取JavaEE的思想,正确地进行项目实战。 《Java EE核心框架实战》涵盖了MyBatis 3、Struts 2、Ajax JSON、Spring 4 MVC、Hibernate 4、Spring 4、WebLogic EJB3等主流JavaEE框架的核心

    大小:92.1 MBJava EE

    立即下载
  • Java EE核心框架实战(第二版)

    Java EE核心框架实战(第二版)

    Java EE核心框架实战 第二版 出版时间:2017 《Java EE核心框架实战(第2版)》的宗旨是提高读者学习Java EE的效率,增强其项目实战能力。为此,本书摒弃了软件公司中不常用或不实用的技术,而是采用近200个开发案例,为读者讲解了开发商业软件的知识,帮助读者进行“精要”式的学习,汲取Java EE的思想,正确地进行项目实战。《Java EE核心框架实战(第2版)》涵盖了MyBatis 3、Struts 2、Ajax、JSON、jQuery、Spring 4 MVC、Hibernate 5、

    大小:24.72MBJava

    立即下载
  • Java高手真经应用框架卷:Java Web核心框架

    Java高手真经应用框架卷:Java Web核心框架

    Java高手真经:JavaWeb核心框架(应用框架卷) 作者:刘中兵Java研究室编著 出版时间:2009-3-1 【图书简介】 本书首先分析了JavaWeb应用的分层设计方法,并进行应用框架的选型,然后讲解各种JavaWeb应用框架、集成技术、实战开发。主要内容包括如下。持久层框架Hibernate:讲解Hibernate入门与核心技术,分别实现MySQL、Oracle、SQLServer数据库的信息系统开发。持久层框架iBATIS:讲解iBATIS入门与核心技术,分别实现MySQL、Oracle、SQ

    大小:150.76MBJava

    立即下载
  • Java EE互联网轻量级框架整合开发

    Java EE互联网轻量级框架整合开发

    本书从入门到实际工作要求讲述了SSM框架的技术应用,提高系统性能,NoSQL(尤其是Redis)在互联网系统中已经广泛使用,从原理到实践全面讲解SSM Redis技术应用

    大小:920 MBJava

    立即下载
  • Java EE互联网轻量级框架整合开发:SSM框架和Redis实现

    Java EE互联网轻量级框架整合开发:SSM框架和Redis实现

    随着移动互联网的兴起,以Java技术为后台的互联网技术占据了市场的主导地位,而在Java互联网后台开发中,SSM框架(Spring Spring MVC MyBatis)成为了主要架构,《 Java EE互联网轻量级框架整合开发

    大小:489.1 MBJavaEE

    立即下载

更多回答

4小时19分钟前回答

Java集合框架学习视频之SpringMVC的组件解析

今天,让我们一起来看看SpringMVC的组件解析,主要内容有SpringMVC的执行流程、SpringMVC组件解析、SpringMVC注解解析和SpringMVC的XML配置解析。下面一起来看看详细内容吧~ 1.SpringMVC的执行流程(参照下图) (1)用户发送请求至前端控制器DispatcherServlet。 (2)DispatcherServlet收到请求调用HandlerMapping处理器映射器。 (3)处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。 (4)DispatcherServlet调用HandlerAdapter处理器适配器。 (5)HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。 (6)Controller执行完成返回ModelAndView。 (7)HandlerA……

12小时30分钟前回答

Java集合框架源码分析之LinkedHashMap详解

LinkedHashMap简介 LinkedHashMap是HashMap的子类,与HashMap有着同样的存储结构,但它加入了一个双向链表的头结点,将所有put到LinkedHashmap的节点一一串成了一个双向循环链表,因此它保留了节点插入的顺序,可以使节点的输出顺序与输入顺序相同。 LinkedHashMap可以用来实现LRU算法(这会在下面的源码中进行分析)。 LinkedHashMap同样是非线程安全的,只在单线程环境下使用。 LinkedHashMap源码剖析 LinkedHashMap源码如下(加入了详细的注释): package java.util; import java.io.*; public class LinkedHashMapK,V extends HashMapK,V implements MapK,V { private static final long serialVersionUID = 3801124242820219131L; //双向循环链表的头结点,整个LinkedHashMap中只……