Java集合总结

Java的集合类主要是由两个接口派生出来的:Collection 和Map

  • Collection
    • Set 无序集合 不可重复
      • EnumSet
      • SortedSet
        TreeSet
      • HashSet
        LinkedHashSet
    • Queue 队列
      • Deque
        ArrayDeque
        LinkedList
      • PriorityQueue
    • List 有序集合 元素可以重复
      • ArrayList
      • LinkedList
      • Vector
        stack
  • Map
    • EnumMap
    • IdentityHashMap
    • HashMap(线程不安全,key value 可以为null)
      • LinkedHashMap
    • Hashtable (线程安全key value 不能为null )
      • Properties
    • SortedMap
      • TreeMap
    • WeekHashMap
  • Iterator 用来集合遍历

    各个集合的特点

    Set集合

    HashSet 类

    特点:
  1. 不能保证元素的排列顺序,顺序有可能发生变换
  2. 不是同步的,如果是多线程程序,需要使用线程代码,来保证同步
  3. 集合元素可以为null
  4. HashSet 集合判断两个元素相等是通过两个对象执行equals()方法比较并且两个对象的hashCode()方法返回值也要相等。

补充: hash 算法的功能 - hash算法的价值在于速度,它可以保证查询速度被快速执行。当需要查询集合中某个元素的时候,hash算法可以直接根据该元素计算出该元素的存储位置,从而可以让程序快速定位该元素。

HashSet中每个能存储元素的“槽位”通常称为“桶”,如果有多个元素的hashCo de值相同,但他们通过equals()方法返回false,这样一个“桶”里面就会放多个元素,会导致性能下降。

LinkedHashSet

是HashSet的子类,与父类的不同在于该类使用链表维护元素的次序,这样使得元素看起来是按照插入顺序保存的。
LinkedHashSet是因为使用了链表维护元素的次序,因此性能相对低于父类,但是迭代访问的时候将会有很好的性能。

TreeSet

TreeSet可以确保集合元素处于排序状态(排序状态指的是根据值的实际大小),除了haseset的方法之外,treeset提供了一些额外的方法

  • Comparator comparator() 如果truest 采用了定制的排序,则该方法返回定制排序所使用的Comparator ,如果采用的是自然的排序,那么这个方法返回null
  • first() 返回集合元素中的第一个元素
  • last() 返回集合元素中的最后一个元素
  • lower(object e) 返回集合元素中位于指定元素之前的元素(即小于指定元素的最大元素)
  • higher(object e) 返回集合中位于指定元素之后的元素 (即大于指定元素的最小元素)
  • subSet(from,to) 返回集合的子集合,范围从from 到to
  • headSet(toele) 返回集合的子集,由小于toele的元素组成
  • tailSet(fromele) 返回集合的子集,由大于或等于fromele的元素组成

treeset的排序

TreeSet 按照红黑树的数据结构进行存储,支持两种排序。
如果想要在集合treeSet中添加对象的话,该对象就需要实现Comparable接口。
comparable该接口定义了一个compareTo(Object obj)方法,该方法返回一个整数值。obj1.compareTo(obj2)如果该方法返回0,则表明这两个对象是相等的,如果返回一个正整数,则表明obj1 大于obj2,如果该方法返回一个负整数,则表明obj1小于obj2。

  • 自然排序
    默认情况下是按照自然排序的方法进行排序的,即比较集合的大小,然后按照升序排列。
    注意:如果添加的对象的比较是根据一个可变Field的字段,进行比较的情况。
    如果是修改了Field字段,再次试图删除该对象的时候,Treeset里面的元素处于无序的状态,删除一个没有改变过的数据后集合中的元素会进行重新索引,接下来就可以删除集合中的所有的元素了。
  • 定制排序
    如果实现定制排序,则可以通过Comparator 接口的帮助。该接口里包含一个in t compare(T o1,T o2)方法,该方法可以用于比较o1和o2的大小。如果需要实现定制排序,则需要在创建TreeSet集合对象的时候,提供一个Comparator对象与该TreeSet 集合关联。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class M {
int age ;
public M(int age){
this.age = age;
}
public String toString() {
return "M[age:"+age+"]";
}
}


import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetTest4 {
public static void main(String[] args) {
TreeSet<M> ts = new TreeSet<M>(new Comparator<M>() {
@Override
public int compare(M o1, M o2) {
// TODO Auto-generated method stub
M m1 = o1;
M m2 = o2;
return m1.age>m2.age?-1:m1.age <m2.age?1:0;
}

});

ts.add(new M(5));
ts.add(new M(-3));
ts.add(new M(9));
System.out.println(ts);
}

}

EnumSet类

EnumSet是一个专门为枚举类设计的集合类,EnumSet中的所有元素必须是指定枚举类型的枚举,集合元素是有顺序,顺序是由定义顺序决定的。

EnumSet内部是以位向量的形式存储的,这种存储形式非常高效,占用内存小,运行效率好,进行批量操作的执行速度非常快。

EnumSet 集合不允许加入null元素。
EnumSet 类没有暴露任何构造器来创建该类的实例,程序应该通过它提供的static方法来创建EnumSet对象。

EnumSet类提供了如下常用的static方法来创建对象

  • allof(Class ele):创建一个包含指定枚举类里所有枚举值的EnumSet集合
  • complementOf(EnumSet s) 创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合
  • copyOf(Collection c) 使用一个普通集合来创建EnumSet集合
  • copyOf(EnumSet s) 创建一个与指定EnumSet 具有相同元素类型、相同集合元素的EnumSet集合
  • noneOf(Class elementType) 创建一个元素类型为指定枚举类型的空EnumSet
  • range(E from ,E rest) 创建包含一个或多个枚举值的EnumSet 集合,传入的多个枚举值必须属于同一个枚举类
  • of(E first,E rest) 创建一个包含一个或多个枚举值的EnumSet集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mport java.util.EnumSet;

enum season{
Sp,Sum,Fal,Win
}

public class TreeSetTest4 {
public static void main(String[] args) {
EnumSet es1 = EnumSet.allOf(season.class);
System.out.println(es1);

EnumSet es2 = EnumSet.noneOf(season.class);
System.out.println(es2);

es2.add(season.Sp);
System.out.println(es2);

EnumSet es3 = EnumSet.complementOf(es1);
es3.add(season.Fal);
System.out.println(es3);
}
}

** 当试图复制一个Collection集合里面的值的时候来创建EnumSet集合时,必须保证Collection集合里面的元素都是同一个枚举类的枚举值。

set类的性能分析以及使用决策

  • HashSet总是比TreeSet好,特别是常用的添加、查询元素。只有当需要维持一个排序的集合的时候才选择TreeSet.
  • HashSet与Lin kedHashSet的比较:hashSet的插入、删除操作要更快一些。LinkedHashSet的遍历操作会更快一些。
  • EnumSet 是所有Set实现类中性能最好的,但是只能保存同一个枚举类的枚举值作为集合元素。
  • 三个实现类都是线程不安全的,如果有多个线程访问set的时候,则必须手动保证该Se t集合的同步。
    通常可以使用synchronizedSortedSet方法来包装
    1
    SortedSet s = Collections.synchronizedSortedSet(new TreeSet());

List集合

Lsit集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。list集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。
List集合可以使用collection集合的所有操作方法。
list里面增加了一些根据索引来操作集合元素的方法。

  • void add(int index ,obj ele)
  • boolean addAll(int index,Collection c )
  • object get(int index) 返回集合index索引处的元素
  • int indexOf(Object o) 返回对象o 在list集合中第一次出现的位置索引
  • int lastIndexOf(obj o) 返回对象o在list中最后一次出现的位置索引
  • obj remove(int index) 删除并返回index索引处的元素
  • List subList(int fromIndex,int toIndex) 返回从索引fromIndex 到索引toIndex处所有集合元素组成的子集合
  • Object set(int index,Object element) 将index索引处的元素替换成element对象
    当调用List集合的set的方法的时候,指定的索引必须是Lis t集合的有效索引,不能添加一个大于list长度的索引值。
    • 集合元素判断两个元素相等的方式是 equals 方法。
      equals判断相等的方法是值相等,== 判断相等的方法是指向同一个对象。

list还额外提供了一个listIterator()方法,该方法返回一个ListIterator对象,增加了下面的方法

  • boolean hasPrevious() 返回该迭代器关联的集合是否还有上一个元素
  • Object previous() 返回该迭代器的上一个元素
  • void add() 在指定的位置增加一个元素

    ArrayList和Vector实现类

    (vector 是一个古老的集合,有很多缺点,不建议使用,Ar ra yList是线程不安全的,Vector是线程安全的)
  • 完全支持前面提到的List接口的全部功能
  • 都是基于数组实现的List类
  • 这两个对象都是使用initialCapacity 参数来设置数组的长度,当数组的长度改变的时候可以initialCapacity回自动增加
  • void ensureCapacity(int minCapacity) 当向实现类中增加大量的元素的时候,该方法可以一次性的增加mincapacity大小的
  • void trimToSize() 调整ArrayList或vector集合的Obj[] 数组长度为当前元素的个数。减少使用空间
  • vector 集合实现了一个Stack的子类。实现了栈的方法,peek(),pop(),push()方法。

    固定长度的List

    前面讲数组的时候介绍了一个操作数组的工具类:Arrays,该工具类里提供了asList(object …a) 方法,该方法可以把一个数组或指定个数的对象转换成List集,这个list既不是ArrayList实现类的实例,也不是Vector实现类的实例,而是Arrays的内部类ArrayList的实例。
    Arrays.ArrayList是一个固定长度的List集合,程序只能遍历访问该集合里面的元素,不能增加、删除该集合里面的元素。
    1
    2
    3
    4
    5
    6
    List fixedList = Arrays.asList("疯狂Java讲义","轻量级Java EE企业级应用实战");
    System.out.println(fixedList.getClass());
    for(int i=0;i<fixedList.size();i++) {
    System.out.println(fixedList.get(i));
    }
    //试图增加、删除元素都会引发异常

Queue集合

用于模拟队列这种数据结构,队列通常是指“先进先出”的容器。

Queue接口中定义了以下几个方法:

  • void add(Object e): 将指定元素加入到这个队列的尾部
  • Object element(): 获取队列头部的元素,但是不删除队列中该元素
  • boolean offer(Object e) 将指定元素加入到此队列的尾部
  • Object peek() 获取队列头部的元素 但是不删除该元素,队列为空就返回null
  • Object poll() 获取队列头部元素,并且删除这个元素

Queue接口有一个PriorityQueue 实现类。Queue还有一个Deque接口,Deque代表一个“双端队列”,双端队列可以同时从两端来添加、删除元素。

PriorityQueue实现类

这个队列是一个比较标准的队列实现类,之所以说它是比较标准的队列实现,是因为这个队列的保存不是按照加入队列的顺序保存的,而是按照队列元素的大小进行重新排序,取出的时候是先取出元素最小的那个元素,而不是首先插入的元素。(在这个意义上已经违背了队列的先进先出)

1
2
3
4
5
6
7
8
PriorityQueue<Integer> pro = new PriorityQueue<Integer>();
pro.offer(3);
pro.offer(9);
pro.offer(1);
System.out.println(pro);
System.out.println(pro.poll());
System.out.println(pro.poll());
System.out.println(pro.poll());
1
2
3
4
[1, 9, 3]
1
3
9

可以发现,如果是直接输出队列的话,会使用toString()返回值,受String的影响,会导致输出的序列没有按照顺序输出,但是如果我们使用poll()的话,就是按照从小到大的顺序。

PriorityQueue 不允许插入null元素,因为它需要对队列中元素进行排序。

  • 自然排序
    自然排序的元素必须实现了Comparable接口。
  • 定制排序
    创建PriorityQueue队列的时候,传入一个Comparator 对象,该对象负责对队列中的所有元素进行排序,不要求队列元素实现Comparator的接口。

    Deque 接口与ArrayDeque实现类

    Deque接口是Queue接口的子接口,代表了一个双端队列,允许从两端来操作队列的元素。可以当作双端队列或者栈使用
  • addFirst()
  • addLast()
  • Iterator descendingIterator() 返回该双端队列对应的迭代器,该迭代器按照逆向顺序迭代队列
  • getFirst()
  • getLast()
  • offerFiirst()
  • offerLast()
  • peekFirst()
  • peekLast()
  • pollFirst()
  • pollLast()
  • pop() 相当于removeFirst
  • push() 相当于addFirst
  • obj removeFirst() 获取并删除该双端队列的第一个元素
  • obj removeFirstOccurrence(obj o) 删除该双端队列的第一个出现的元素o
  • removeLast()获取并删除该双端队列的最后一个元素
  • removeLastOccurrence(obj o) 删除该双端队列最后一次出现的元素o
    ArrayDeque是Deque的基于数组的实现类。

    LinkedList

    是List接口的实现类,意味着这是Lis t的一个集合,可以根据索引来随机访问集合中的元素,还实现了De que接口,因此也可以当作双端队列使用,也可以当作栈使用。

LinkedList是一个功能非常强大的集合,与ArrayList以及ArrayDeque的实现机制完全不同,Array是按照数组形式来保存数据的,因此在访问集合元素的时候性能比较好,Linkedlist是根据链表来存储数据的,访问数据的时候性能比较差,但是在插入、删除元素的时候性能比较好。

各种线性表的性能分析

名称 实现机制 随机访问排名 迭代操作 插入操作 删除操作
数组 连续内存区保存元素 1 x x x
ArrayList/ArrayDeque 以数组保存元素 2 2 2 2
Vector 以数组保存元素 3 3 3 3
LinkedList 以链表保存元素 4 1 1 1

java堆内存大小的修改

1
java -Xms128m -Xmx512m PerformanceTest

-Xms 表示设置的JVM的堆内存的初始大小
-Xmx 表示设置的JVM的堆内存的最大大小(不要超过物理内存)

使用建议

  • 如果是遍历List集合
    • ArrayList、Vector使用get来遍历集合元素
    • LinkedList集合 使用迭代器遍历
  • 如果需要经常执行插入删除 操作 则使用LinkedList。如果使用ArrayList或者Vector的话,通常需要重分配内部数组的大小,时间开销经常是LinkedList的几十倍。
  • 多线程访问集合的时候,应该考虑集合的线程安全集合

Map

map的key是不允许重复的,在一个Map对象的任何两个key通过equals方法比较总是返回false。
Set与Map的关系非常的密切,从源码来看,Java是通过先实现了Map,然后通过包装一个所有value都为null的Map就实现了Set集合。
通用方法总结
-clear() 删除该Map对象中所有的key-value对

  • bool containsKey()
  • bool containsValue()
  • Set entrySe() 返回Map集合中所有的key-value对
  • obj get(key)
  • isEmpty()
  • Set keySet()
  • obj put(key,value)
  • void putAll(map)
  • obj remove(key)
  • int size()
  • Collection values()

map中的每一个实体类的方法:

  • obj getKey()
  • obj getValue()
  • obj setValue()

    HashMap 和 Hashtable实现类

    HashTable与HashMap都是Map接口的典型实现,它们之间的关系类似于ArrayList与Vector的关系。HashTable是一个古老的Map实现类。
    区别:
  • Hashtable是一个线程安全的实现,HashMap是线程不安全的。
  • Hashtable不允许使用null作为key和value ,HashMap是可以的。
    Hashtable和HashMap类用作key的对象都必须实现hashCode()方法和equals()方法。
    Hashtable与HashMap 列表判断值相等的方法是equals()方法

    LinkedHashMap

    LinkedhashMap 使用双向链表来维护key-value对的次序,该链表负责维护Map的迭代顺序,保证顺序与插入的链表一致。

    Properties 读写属性文件

    (windows中的ini文件就是一种属性文件)
    Properties 类是Hashtable 类的子类,该对象在处理属性文件的时候特别方便。该类可以把Map 对象和属性文件关联起来,从而可以把Map对象中的key-value 对写入属性文件中,也可以把属性文件中的“属性名= 属性值”加载到Map 对象中。
    一共有三个方法修改Properties里面的key和value值
  • String getProperty(String key) : 获取属性文件中指定属性名对应的属性值
  • String getProperty(String key,String defaultValue) 如果文件中不存在指定的key值的时候,会设置default作为默认值。
  • Object setProperty(String key,String value) 设置属性
  • void load(InputStream inStream) 从属性文件中加载key-value对,把加载到的key-value对追加到Propertie里面,不保证次序
  • void store(OutputStream out,String ) 将properties 中的key-value对输出到指定的属性文件中。

这里提供一个读取java中的properties文件的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {
Properties pro = new Properties();
try {
// 读取
pro.load(new FileInputStream(new File("./pro.properties")));
String xx = pro.getProperty("ee");
System.out.println(xx);
pro.setProperty("p", "12323");
System.out.println(pro.getProperty("p"));
//存储
pro.store(new FileOutputStream(new File("./pro.properties")),"test line");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

SortedMap接口和TreeMap实现类

SortedMap接口也有一个TreeMap的实现类,TreeMap就是一个红黑树数据结构,每个key-value对即作为红黑树的一个节点。TreeMap存储key-value对的时候,需要根据key对节点进行排序。TreeMap可以保证所有的key-value对处于有序状态。

  • 自然排序
    key必须实现Comparable接口,而且所有的ke y应该是同一个类的对象。
  • 自定义排序
    创建Treemap的时候,需要传入一个Comparator对象,该对象负责对Treemap 中的所有的key进行排序。

    如果使用自定义作为Treemap的key的时候,如果想要让TreeMap良好的工作,则重写该类的equals()方法和compareTo()方法时保持一致的返回结果,两个key 通过equals()方法比较返回true时,它们通过compareTo()方法。

  • Map.Entry firstEntry():返回该Map中的最小值,如果该Map为空或不存在这样的key,则都返回null

  • firstKey() 返回该Map中最小key值,如果该Map为空,则返回null
  • Map.Entry lastEntry(): 返回map中最大key值
  • Map.Entry higherEntry(obj key) 返回该Map中位于后一位的key-value 对。如果该Map为空,则返回null
  • Object higherKey(object key) 返回该Map中位于key后一位的key值
  • Map.Entry lowerEntry(obj key) 返回该Map中位于key 前一位的key-value对
  • Object lowerKey(obj key) 返回该Map中位于key前一位的ke y值
  • NavigableMap subMap(obj fromkey, bool from, obj toKey ,bool toin) 返回map的子集,是否包含fromKey 与 toKey主要取决于 后面的bool值
  • SortedMap tailMap(obj fromKey) 返回map的子map,其key 的范围是大于fromKey的。
  • SortedMap headMap(obj toKey) 返回该map的子Map,其key的范围是小于hokey的所有的key
  • Navigatable headMap(obj tokey,bool inclu) tokey是否包含取决于bool的值

    weakHashMap实现类

    与HashMap的用法是一样的,只不过HashMap是强引用的,只要HashMap对象不被销毁,那么所有的key就都不会被垃圾回收机制回收,也不会自动删除这些key对应的key-value对。但是weakHashMap是弱引用的,如果该对象的key 没有被强引用变量引用,则这些key所引用的对象可能被垃圾回收,也可能自动删除这些key 所对应的key-value对。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class test {
    public static void main(String[] args) {
    WeakHashMap<String, String> whm = new WeakHashMap<String, String>();
    whm.put(new String("语文"), new String("良好"));
    whm.put(new String("数学"), new String("及格"));
    whm.put(new String("英文"), new String("中等"));
    System.out.println(whm);
    whm.put("java","dsdfs");
    System.gc();
    System.runFinalization();
    System.out.println(whm);
    }
    }
    //结果
    {英文=中等, 数学=及格, 语文=良好}
    {java=dsdfs}

从上面的程序中,我们可以看出,在系统进行垃圾回收的时候,前面new的对象全部被回收了,但是使用字符串java的变量还在,这是因为前面三个都是匿名的对象,weakHashMap只保留了它的弱引用,但是第四个的key是一个字符串直接量,系统会保留它的强引用,所以垃圾回收机制不会回收。

IdentityHashMap实现类

这个实现类与HashMap的类是实现机制是相同的,主要的区别在于当且仅当两个key严格相等的时候(key1 == key2)的时候,该类才能判定两个ke y相等。对于普通的HashMap而言,只要key1 和key2 通过equals()方法比较返回true,且它们的hashCode值相等即可。

EnumMap 实现类

EnumMap是一个与枚举类一起使用的map实现,EnumMap中的所有key必须是单个枚举类的枚举值。创建EnumMap的时候,必须显示或者隐示的指定它对应的枚举类。
根据key的自然顺序来维护key-value 对的顺序。
EnumMap 不允许使用null作为key,但是允许使用null作为value.
创建EnumMap的时候,必须指定一个枚举类,从而将该EnumMap和指定枚举类关联起来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.EnumMap;

enum Season{
SPRING,SUMMER,FALL,WINTER
}

public class test {
public static void main(String[] args) {
EnumMap<Season, String> sE = new EnumMap<Season, String>(Season.class);
sE.put(Season.FALL, "dsdf");
sE.put(Season.SPRING, "dsdfsd");
System.out.println(sE);
}
}

Map实现类的性能分析

  • HashMap与Hashtable的效率大致相同,实现机制几乎一样,但是Hashtable是线程同步的。
  • TreeMap 通常比HashMap、Hashtable要慢,因为TreeMap 底层采用红黑树来管理。
  • 对于一般的应用场景,程序应该多考虑使用HashMap,因为HashMap正是为查询设计的。
  • LinkedHashMap比HashMap 慢一点,因为它需要维护链表来保持Map中的key-value时的添加顺序。

    HashSet 和 HashMap的性能选项

    对于HashSet及其子类而言,它们采用hash算法来决定集合中元素的存储位置,并通过hash算法来控制集合的大小;对于HashMap、Hashtable及其子类而言,它们采用hash算法来决定Map中key的存储,并通过hash算法来增加key集合的大小。
    hash表里面可以存储元素的位置被称为“桶”,通常情况下,单个“桶”里面存储一个元素,此时有最好的性能。

    操作集合的工具类:Collections

    Java提供了一个Set、List和Map的工具类:Collection,该工具类里面提供了大量的方法可以对集合进行排序、删除、查找、设置集合为不可变、对集合对象实现同步控制等方法。

    排序操作

  • static void reverse(List list) 反转指定集合的元素
  • static void shuffle(List list) 对集合元素进行随机排序
  • static void sort(List list) 根据自然排序对集合进行升序排序
  • static void sort(List list,Comparator c) 根据指定的规则对集合进行排序
  • satic void swap(List list, int I,int j) 将指定的Lis t集合中的I处的元素和j处的元素进行交换。
  • static void rotate(List list, int distance)
    • distance 为正数的时候,将list集合的后distance 个元素“整体”移到前面
    • 为负数的时候,将list集合的前distance 个元素整体移到后面
      使用语法:
      1
      2
      3
      4
      5
      6
      7
      List<Integer> ls = new ArrayList<Integer>();
      ls.add(1);
      ls.add(2);
      ls.add(3);
      ls.add(4);
      System.out.println(ls);
      Collections.reverse(ls);

查找替换操作

  • static int binarySearch(List list,Object key) 使用二分搜索方法 搜索指定的集合,获得指定对象在集合中的索引
  • static Object max(Collect coll) 根据元素的自然排序,返回集合中的最大元素
  • static Object max(Collection Coll,Comparator comp) 根据指定的排序方法,返回最大的值
  • min 同理
  • static void fill(List list,Object obj) 使用指定元素obj替换指定 List集合中的所有元素
  • static int frequency(Collection c ,Object o) 返回指定集合中指定元素出现的次数
  • static int indexOfSubList(List source,List target): 返回子list对象在父List对象中第一次出现的位置索引;如果父List中没有出现,则返回-1
  • static int lastIndexOfSubList(List source,List target) 返回子List对象在父List中最后一次出现的位置索引
  • static boolean replaceAll(List list,Object oldVal,Object newVal) 使用一个新值newVal替换List对象的所有旧的oldVal

    同步控制

    Collections类中提供了多个synchronizedXxx() 方法,可以将指定的集合包装成线程同步的集合
    1
    2
    Collection c = Collections.synchronizedCollection(new ArrayList())
    List ls = Collections.synchronizedList(new ArrayList());

设置不可变对象

  • emptyXxx() 返回一个空的、不可变的集合对象
  • singletonXxx() 返回一个只包含指定对象的、不可变的集合对象
  • unmodiifiableXxx() 返回指定集合对象的不可变视图
    上面的意思是生成的集合只能读取