1. Java 集合框架概述

一方面, 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。

另一方面,使用Array存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引用放入容器中。

数组在内存存储方面的特点:

  • 数组初始化以后,长度就确定了。
  • 数组声明的类型,就决定了进行元素初始化时的类型
  • 数组存储的数据是有序的、可以重复的
  • 存储数据的特点单一

数组在存储数据方面的弊端:

  • 数组初始化以后,长度就不可变了,不便于扩展
  • 数组中提供的属性和方法少,不便于进行添加、删除、插入等操作,且效率不高。
  • 无法直接获取存储元素的个数   

Java 集合类可以用于存储数量不等的多个对象,还可用于保存具有映射关系的

2. 集合的使用场景

  • 将JSON对象或JSON数组转换为Java对象或Java对象构成的List
  • 将Java对象或Java对象构成的List转换为JSON对象或JSON数组

3. Collection和Map接口继承树

Collection接口:单列数据,定义了存取一组对象的方法的集合

List元素有序、可重复的集合

Set元素无序、不可重复的集合

Map接口:双列数据,保存具有映射关系“key-value对”的集合

4. Collection 接口方法

  • 添加

.add(Object obj)

.addAll(Collection coll)

  • 获取有效元素的个数 int

.size()

  • 清空集合 void

.clear()

  • 是否是空集合 boolean

.isEmpty()

  • 是否包含某个元素 boolean

.contains(Object obj):是通过元素的equals方法来判断是否是同一个对象

.containsAll(Collection c):也是调用元素的equals方法来比

  • 删除 boolean

.remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素

.removeAll(Collection coll):取当前集合的差集

  • 取两个集合的交集 boolean

.retainAll(Collection c):把交集的结果存在当前集合中,不影响c

  • 集合是否相等 boolean

.equals(Object obj)

  • 转成对象数组 Object[]

.toArray()

  • 获取集合对象的哈希值

.hashCode()

  • 遍历

.iterator():返回迭代器对象,用于集合遍历

5. Iterator 接口

  • Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
  • GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生类似于“公交车上的售票员”、“火车上的乘务员”、“空姐”。
  • Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象。
  • Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合。
  • 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。

Iterator接口的方法

.hasNext()

.next( )

.remove( )

在调用it.next()方法之前必须要调用it.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常

Iterator接口remove()方法

Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。

如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException

6. foreach 循环

  • Java 5.0 提供了 foreach 循环迭代访问 Collection和数组。
  • 遍历操作不需获取Collection或数组的长度,无需使用索引访问元素。
  • 遍历集合的底层调用Iterator完成操作。
  • foreach还可以用来遍历数组

7. List接口

  • 鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组
  • List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  • JDK API中List接口的实现类常用的有:ArrayListLinkedList和Vector。

List接口方法

List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法

.add(int index, Object ele):在index位置插入ele元素 boolean

.addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来 Object

.get(int index): 获取指定index位置的元素 int

.indexOf(Object obj):返回obj在集合中首次出现的位置 int 

.lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置 Object

.remove(int index):移除指定index位置的元素,并返回此元素 Object

.set(int index, Object ele):设置指定index位置的元素为ele List

.subList(int fromIndex, int toIndex):返回从fromIndextoIndex

8. ArrayList

ArrayList 是 List 接口的典型实现类、主要实现类

本质上,ArrayList是对象引用的一个变长数组

ArrayListJDK1.8之前与之后的实现区别?

JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组

JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组

Arrays.asList(…) 方法返回的 List 集合,既不是 ArrayList 实例,也不是Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合

ArrayList源码分析

//数组属性
    private transient Object[] elementData;
//无参构造
    public ArrayList() {
        this(10);
}
//初始化数组长度
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
}
//添加元素
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
}
//元素数量大于数组长度时
    private void ensureCapacityInternal(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
}
//正常情况下扩展1.5倍
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;  //10
        int newCapacity = oldCapacity + (oldCapacity >> 1);//右位移相当于除以2
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
}


       //jdk 8中ArrayList的变化:
       ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没有创建长度为10的数组
       list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
       后续的添加和扩容操作与jdk 7 无异。

9. LinkedList

对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高

新增方法:

.addFirst(Object obj)

.addLast(Object obj)

.getFirst()

.getLast()

.removeFirst()

.removeLast()

LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量:

prev变量记录前一个元素的位置

next变量记录下一个元素的位置

LinkedList源码解析

//基本属性
    transient int size = 0;
    transient Node<E> first;//集合第一个元素
    transient Node<E> last;//集合最后一个元素



//Node属性
        E item;  //当前节点
        Node<E> next;  //下一个节点
        Node<E> prev;  //上一个节点



//添加元素方法
    public boolean add(E e) {
        linkLast(e);
        return true;
}
//如果是第一次添加last为null,l=null,把新节点赋给last和first属性
//如果第二次添加,last不为空 l不为空,新节点把l作为自己的first,新节点赋给last,新节点赋给l的next属性
    void linkLast(E e) {
        final Node<E> l = last;  //last=1号元素  l=1号元素
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        //修改次数
        modCount++;
    }

10. Vector

Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的

在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。

新增方法:

.addElement(Object obj)

.insertElementAt(Object obj,int index)

.setElementAt(Object obj,int index)

.removeElement(Object obj)

.removeAllElements()

ArrayList和LinkedList的异同

二者都线程不安全,执行效率高,线程安全的Vector。此外,ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。对于新增和删除操作add(特指插入)和remove,LinkedList比较占优势,因为ArrayList要移动数据。

ArrayList和Vector的区别

Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同步类。因此开销就比ArrayList要大,访问要慢。正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。Vector还有一个子类Stack。

11. Set 接口

Set接口是Collection的子接口,set接口没有提供额外的方法

Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。

Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法

Set 无序性不等于随机性,不是指遍历时的输出顺序,无序性指的是在存储元素时位置的不确定性

12. HashSet

HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。

HashSet 是数组和链表的结合体

HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。

HashSet 具有以下特点:

不能保证元素的排列顺序

HashSet 不是线程安全的

集合元素可以是 null

HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。

对于存放在Set容器中的对象,对应的类一定要重写equals()hashCode(Object obj)

HashSet中添加元素的过程

当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据 hashCode 值,通过某种散列函数决定该对象在 HashSet 底层数组中的存储位置。hashCode() 方法可以简单的理解成一个随机函数(这个散列函数会与底层数组的长度相计算得到在数组中的下标,并且这种散列函数计算还尽可能保证能均匀存储元素,越是散列分布, 该散列函数设计的越好)

如果两个元素的hashCode()值相等,会再继续调用equals方法,如果equals方法结果为true,添加失败;如果为false,那么会保存该元素,但是该数组的位置已经有元素了,那么会通过链表的方式继续链接。

如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置 , 但依然可以添加成功

重写 hashCode()和equals()方法的基本原则

相等的对象必须具有相等的散列码

在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。

当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode()方法的返回值也应相等。

对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。

Eclipse/IDEA工具里hashCode()的重写

	@Override
	public int hashCode() {
		//31是放大系数,系数越大,通过计算出现重复的几率就越小
		//也不能太大,太大容易数据溢出
		//要是个素数
		//采用2的幂-1的方案,例如:2的1次方-1 是1  2的2次方-1是3 2的三次方-1是7 2的四次方-1是15 2的5次方-1 是31 2的6次方-1是63,其中3 7 31是素数,3和7太小,因此用31做放大系数
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

13. LinkedHashSet

LinkedHashSet 是 HashSet 的子类

LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。

LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。

LinkedHashSet 不允许集合元素重复(原理同HashSet)

14. TreeSet

TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态

不能添加不同类的对象

没有重写Comparator方法不能添加对象

TreeSet底层使用红黑树结构存储数据 

新增的方法如下: (了解)

.Comparator comparator()

.Object first()

.Object last()

.Object lower(Object e)

.Object higher(Object e)

.SortedSet subSet(fromElement, toElement)

.SortedSet headSet(toElement)

.SortedSet tailSet(fromElement)

lTreeSet 两种排序方法:自然排序定制排序。默认情况下,TreeSet

15. 红黑树

小数存左边,大数存右边

参考资料:数据结构概述-Java版

16. 自然排序

TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列 

如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable接口

实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过compareTo(Object obj) 方法的返回值来比较大小。

Comparable 的典型实现:

BigDecimal、BigInteger 以及所有的数值型对应的包装类:按它们对应的数值大小进行比较

Character:按字符的 unicode值来进行比较

Boolean:true 对应的包装类实例大于 false 对应的包装类实例

String:按字符串中字符的 unicode 值进行比较

Date、Time

向 TreeSet 中添加元素时,只有第一个元素无须比较compareTo()方法,后面添加的所有元素都会调用compareTo()方法进行比较。

因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象。

对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 方法比较返回值。

当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0。否则,让人难以理解

17. 定制排序

TreeSet的自然排序要求元素所属的类实现Comparable接口,如果元素所属的类没有实现Comparable接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator接口来实现。需要重写compare(T o1,T o2)方法

利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。

此时,仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。

使用定制排序判断两个元素相等的标准是:通过Comparator比较两个元素返回了0

18. Map接口继承树

19. Map接口

Map与Collection并列存在。用于保存具有映射关系的数据:key-value 

Map 中的 key 和 value 都可以是任何引用类型的数据 

Map 中的 key Set来存放,不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()equals()方法 

常用String类作为Map的“键” 

key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value

Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是 Map 接口使用频率最高的实现类 

20. jdk7中HashMap的存储原理

  • 在实例化以后,底层创建了长度是16的一维数组Entry[] table
  • 执行map.put(key1,value1)后
  • 调用key1所在类的hashCode()计算key1哈希值
  • key1哈希值经过某种算法计算以后,得到在Entry数组中的存放位置
  • 如果此位置上的数据为空,此时的key1-value1添加成功。 ----情况1
  • 如果此位置上的数据不为空,如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。----情况2
  • 如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,equals()返回false:此时key1-value1添加成功。----情况3
  • 如果equals()返回true:使用value1替换value2。--情况4
  • 关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。

21. jdk8中HashMap的存储原理

  1. new HashMap():底层没有创建一个长度为16的数组
  2. jdk 8底层的数组是:Node[],而非Entry[]
  3. 首次调用put()方法时,底层创建长度为16的数组
  4. jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树
  5. 当数组的某一个索引位置上的元素以链表形式存在的数据个数 > 8 且当前数组的长度 > 64时,此时此索引位置上的所数据改为使用红黑树存储

22. jdk8中hashMap源码解析

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
    	//jdk8中hashmap底层是Node数组不再是entry数组
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        //如果table数组为空,初始化数组
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        //通过hash值计算位置,并且位置上没有元素,添加元素
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
        	
            Node<K,V> e; K k;
            //如果hash值相等并==或equals为true,把元素赋值给e,最终实现替换
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
            	//如果元素本身是一个TreeNode,调用putTreeVal添加元素
                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);
                        //如果链表的个数超过8,则进行红黑树的处理
                        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;
            }
        }
        //元素数量加1
        ++modCount;
        //元素数量超过阈值,扩容
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
    /**
     * 	对链表进行红黑树的处理
     */
    final void treeifyBin(Node<K,V>[] tab, int hash) {
        int n, index; Node<K,V> e;
        //如果数组为null或者数组长度小于64进行扩容,不进行红黑树处理
        if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
            resize();
        else if ((e = tab[index = (n - 1) & hash]) != null) {
            TreeNode<K,V> hd = null, tl = null;
            //使用循环处理红黑树
            do {
                TreeNode<K,V> p = replacementTreeNode(e, null);
                if (tl == null)
                    hd = p;
                else {
                    p.prev = tl;
                    tl.next = p;
                }
                tl = p;
            } while ((e = e.next) != null);
            if ((tab[index] = hd) != null)
                hd.treeify(tab);
        }
    }

23. 常用方法

添加、删除、修改操作:

.put(Object key,Object value):将指定key-value添加到(或修改)当前map对象 Object

.putAll(Map m):将m中的所有key-value对存放到当前map中 void

.remove(Object key):移除指定key的key-value对,并返回value Object

.clear():清空当前map中的所有数据 void

元素查询的操作:

.get(Object key):获取指定key对应的value Object

.containsKey(Object key):是否包含指定的key boolean

.containsValue(Object value):是否包含指定的value boolean

.size():返回map中key-value对的个数 int

.isEmpty():判断当前map是否为空 boolean

.equals(Object obj):判断当前map和参数对象obj是否相等 boolean

元视图操作的方法:

Set keySet():返回所有key构成的Set集合

Collection values():返回所有value构成的Collection集合

Set entrySet():返回所有key-value对构成的Set

关于映射关系的key是否可以修改?

不要修改 映射关系存储到HashMap中会存储key的hash值,这样就不用在每次查找时重新计算每一个Entry或Node(TreeNode)的hash值了,因此如果已经put到Map中的映射关系,再修改key的属性,而这个属性又参与hashcode值的计算,那么会导致匹配不上

负载因子值的大小,对HashMap有什么影响

负载因子的大小决定了HashMap的数据密度。

负载因子越大密度越大,发生碰撞的几率越高,数组中的链表越容易长, 造成查询或插入时的比较次数增多,性能会下降。

负载因子越小,就越容易触发扩容,数据密度也越小,意味着发生碰撞的几率越小,数组中的链表也就越短,查询和插入时比较的次数也越小,性能会更高。但是会浪费一定的内容空间。而且经常扩容也会影响性能,建议初始化预设大一点的空间。

按照其他语言的参考及研究经验,会考虑将负载因子设置为0.7~0.75,此时平均检索长度接近于常数

24. LinkedHashMap

LinkedHashMap 是 HashMap 的子类

在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序

与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

源码解析:

  • put方法调用HashMap的put方法,以及putVal方法
  • 重写了newNode方法
  • LinkedHashMap.Entry继承了HashMap.Node

25. TreeMap

TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。

TreeSet底层使用红黑树结构存储数据

TreeMap 的 Key 的排序:

自然排序

TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException

定制排序

创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现Comparable 接口

TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0

26. Properties

Properties 类是 Hashtable 的子类,该对象用于处理属性文件 

由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 keyvalue 都是字符串类型 

存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法

27. Collections工具类

Collections 是一个操作 Set、List 和 Map 等集合的工具类

Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法

排序操作(均为static方法)

reverse(List):反转 List 中元素的顺序

shuffle(List):对 List 集合元素进行随机排序

sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序

sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序

swap(List,int, int):将指定 list 集合中的 i 处元素和 j

查找、替换

Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素

Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素

Object min(Collection)

Object min(Collection,Comparator)

int frequency(Collection,Object):返回指定集合中指定元素的出现次数

void copy(List dest,List src):将src中的内容复制到dest中

boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List

Collections常用方法:同步控制

Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题

CollectionCollections的区别

collection是接口,Collections是操作集合的工具类

Enumeration

lEnumeration 接口是 Iterator 迭代器的 “古老版本”

Enumeration stringEnum = new StringTokenizer("a-b*c-d-e-g", "-"); 
while(stringEnum.hasMoreElements()){ 
Object obj = stringEnum.nextElement(); 
System.out.println(obj); 
}

Empty spaces,fill the pages.