数据结构,Collection集合和Collections工具类
数据结构
- Java常见的集合数据
数据结构的说明
数组
- 无序数组
- 优点:查询快,如果知道索引可以快速地存取
- 缺点:删除慢,大小固定
- 有序数组
- 优点:比无序数组查找快
- 缺点:删除和插入慢,大小固定
栈
- 优点:提供后进先出的存取方式
- 缺点:存取其他项很慢
- 比如,Android中管理activity进出就是使用栈
队列
- 优点:提供先进先出的存取方式
- 缺点:存取其他项都很慢
链表
- 优点:插入快,删除快
- 缺点:查找慢(一个个节点查)
二叉树
- 优点:查找,插入,删除都快(平衡二叉树)
- 缺点:删除算法复杂
红-黑树
- 优点:查找,插入,删除都快,树总是平衡的(局部调整)
- 缺点:算法复杂
哈希表
- 优点:如果关键字已知则存取速度极快,插入快
- 缺点:删除慢,如果不知道关键字则存取很慢,对存储空间使用不充分
堆
- 优点:插入,删除快,对最大数据的项存取很快
- 缺点:对其他数据项存取很慢
图
- 优点:对现实世界建模
- 缺点:有些算法慢且复杂
集合
为什么出现集合类?
- 为了方便对多个对象进行操作,我们就必须把这多个对象进行存储。而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的变量,
- 在我们目前所学过的知识里面,有哪些是容器类型有数组和StringBuffer。
- StringBuffer的结果是一个字符串,不一定满足我们的要求,所以我们只能选择数组,这就是对象数组。
- 而对象数组又不能适应变化的需求,因为数组的长度是固定的,这个时候,为了适应变化的需求,Java就提供了集合类供我们使用。
数组与集合的区别
长度区别
- 数组的长度固定
- 集合长度可变
内容不同
数组存储的是同一种类型的元素
而集合可以存储不同类型的元素
元素的数据类型问题
数组可以存储基本数据类型,也可以存储引用数据类型
集合只能存储引用类型
性能上
- 数组更好
- 集合底层数据结构复杂
集合继承树
Set集合
一般使用的有TreeSet和HashSet,数据不能重复
TreeSet
- 基于红黑树实现,支持有序性操作,放入数据不能重复且不能为null
- 但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 则为 O(logN)。
- 可以重写compareTo()方法来确定元素大小,从而进行升序排序。
HashSet
- HashSet是根据hashCode来决定存储位置的,是通过HashMap实现的(map(值,null)),所以对象必须实现hashCode()方法,
- 存储的数据无序不能重复,可以存储null,但是只能存一个。
- 查找的时间复杂度为 O(1),
LinkedHashSet:
- 具有 HashSet 的查找效率,且内部使用双向链表维护元素的插入顺序。
List集合
List比较常用的有ArrayList和LinkedList,还有一个比较类似的Vector
ArrayList
- 是使用动态数组来实现的,对于数据的随机get和set或是少量数据的插入或删除,支持随机访问,效率会比较高。
- ArrayList是线程不安全的,在不考虑线程安全的情况下速度也比较快的。
- ArrayList插入数据可以重复,也是有序的,按照插入的顺序来排序。
- 根据序号读取数据只需直接获取数组对应脚表的数据
LinkedList
- 内部是基于双向链表实现的形式来实现的,只能顺序访问,但是可以快速地在链表中间插入和删除元素。不仅如此,LinkedList 还可以用作栈、队列和双向队列。。
- LinkedList根据序号获取数据,是二分进行遍历,如果序号小于总长度的一半,就从链表头部开始往后遍历,直到找到对应的序号。如果序号大于总长度的一半,就从链表尾部往前进行遍历,直到找到对应的序号。拿到数据。
Vector
- Vector的使用方法和内部实现基本和ArrayList相同,只不过它在add(), remove(), get()等方法中都加了同步。所以它是线程安全的。但是使用效率上就不如ArrayList了。
Map集合
HashMap
- HashMap是基于哈希表来实现的,简单的来说,根据key算出一个hash值,确定一个存放index,但是hash值有可能会冲突重复,所以如果冲突的hash值就需要以链表的形式在同一个index存放了。
TreeMap
- TreeMap的使用大致跟HashMap类似,但是内部实现是根据红黑树来实现的。红黑树是一种平衡有序的二叉树,TreeMap的插入删除查询都是依据红黑树的规则来进行的。
HashTable
- HashMap和TreeMap都是线程不安全的,多线程操作的时候可能会造成数据错误。Hashtable是线程安全的。其他内部实现,与HashMap都是一样的。
- 意味着同一时刻多个线程可以同时写入 HashTable 并且不会导致数据不一致。它是遗留类,不应该去使用它。
- 现在可以使用 ConcurrentHashMap 来支持线程安全,并且 ConcurrentHashMap 的效率会更高,因为 ConcurrentHashMap 引入了分段锁。
LinkedHashMap:使用双向链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU)顺序。
Java 集合框架中的队列 Queue
什么是队列
- 队列是数据结构中比较重要的一种类型,它支持 FIFO,尾部添加、头部删除(先进队列的元素先出队列),跟我们生活中的排队类似。
队列的种类
- 单队列(单队列就是常见的队列, 每次添加元素时,都是添加到队尾,存在“假溢出”的问题也就是明明有位置却不能添加的情况)
- 循环队列(避免了“假溢出”的问题)
Java 集合中的 Queue 继承自 Collection 接口 ,Deque, LinkedList, PriorityQueue, BlockingQueue 等类都实现了它。
- Queue 用来存放 等待处理元素 的集合,这种场景一般用于缓冲、并发访问。除了继承 Collection 接口的一些方法,Queue 还添加了额外的 添加、删除、查询操作。
- LinkedList:可以用它来实现双向队列。
- PriorityQueue:基于堆结构实现,可以用它来实现优先队列。
Collection接口
java.util.Collection下的接口和继承类关系简易结构图:
- 存储单列数据,可以重复,无序
常用的方法
方法名 | 描述 |
---|---|
size() | 查看集合的长度 |
boolean add(Object obj) | 往集合中添加元素 |
boolean addAll(Object obj) | 将集合中的所有元素添加到当前集合中,只要当前集合发生改变true |
void clear() | 清除集合中的所有元素 |
boolean remove(Object obj) | 将元素添从当前集合中删除,只要当前集合发生改变true |
boolean removeAll(Collection c) | 将集合中的所有元素从当前集合中删除 |
removeIf() | 带条件删除,重写Predicate接口的test方法 |
boolean contains(Object obj) | 查看元素是否在集合中,有一个就是true |
boolean containsAll(Collection c) | 判断集合元素是否全部在当前集合中,全部在为true |
boolean retainAll(Collecton c) | 判断交集,返回值表示的是集合是否发生过改变。 |
isEmpty() | 查看集合是否为空 |
public T[] toArray(T[] a) | 将集合变为数组 |
Arrays.asList(String[] str) | 数组转集合,不能进行集合长度改变的操作(增加,删除),UnsupportedOperationException |
演示collection的功能
- 集合对象的创建需要通过接口的实现类
Collection c = new Collection(); //错误,因为接口不能实例化
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
System.out.println("isEmpty:" + c.isEmpty());
// 添加数据
c.add("aa");
c.add("bb");
c.add("cc");
// 查看集合的长度
System.out.println("size:" + c.size()); // size:3
// 遍历
for (String s : c) {
System.out.print(s + " "); // aa bb cc
}
System.out.println();
// 添加集合addAll(集合)
c.addAll(c);
System.out.println("addAll:" + c);// addAll:[aa, bb, cc, aa, bb, cc]
// 移除remove(object)
c.remove("aa");
System.out.println("remove:" + c);// remove:[bb, cc, aa, bb, cc]
// 移除集合
Collection<String> d = new ArrayList<>();
d.add("aa");
d.add("bb");
c.removeAll(d);
System.out.println("removeAll:" + c); // removeAll:[cc, cc]
// 带条件删除removeIf
c.add("abc");
// c.removeIf(new Predicate<String>() {
//
// @Override
// public boolean test(String t) {
// return t.length()<=2;
// }
// });
// lambda 表达式
c.removeIf((t) -> t.length() <= 2);
System.out.println("removeIf:" + c); // removeIf:[abc]
// 是否存在参数指定的元素,存在true
System.out.println("contains:" + c.contains("abc")); // contains:true
// 是否存在集合参数中的全部元素,全部存在为true
c.add("aa");
System.out.println("containsAll:" + c.containsAll(d));// containsAll:false,只有aa包含
// 数组转换成集合,Arrays.asList是Arrays的静态内部类
// 不能添加,移除(改变长度)
List<String> list = Arrays.asList(new String[] { "aa", "bb" });
// list.add("cc"); //UnsupportedOperationException
// list.remove("aa"); // UnsupportedOperationException
System.out.println("get:" + list.get(1)); // get:bb
// 集合转数组toArray
Object[] array = d.toArray(new Object[2]);
// Object[] array = d.toArray();
String[] array2 = d.toArray(new String[3]);
// 遍历
System.out.println("toArray:" + Arrays.toString(array));// toArray:[aa, bb, null]
//移除所有元素
c.clear();
System.out.println("clear:" + c);//clear:[]
}交集
- 假设有两个集合A,B。
- A对B做交集,最终的结果保存在A中,B不变。
- 返回值表示的是A是否发生过改变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17System.out.println("retainAll:"+c1.retainAll(c2));
System.out.println("c1:" + c1);
System.out.println("c2:" + c2);
--------------------------------------------------
结果:
retainAll:false
c1:[abc1, abc2, abc3, abc4]
c2:[abc1, abc2, abc3, abc4, abc5, abc6, abc7]
System.out.println("retainAll:"+c2.retainAll(c1));
System.out.println("c1:" + c1);
System.out.println("c2:" + c2);
--------------------------------------------------
结果:
retainAll:true
c1:[abc1, abc2, abc3, abc4]
c2:[abc1, abc2, abc3, abc4]
集合的遍历
转成数组
集合转成数组然后遍历
Object[] toArray()
:把集合转成数组,可以实现集合的遍历
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// 创建集合对象
Collection c = new ArrayList();
// 添加元素
c.add("hello"); // Object obj = "hello"; 向上转型
c.add("world");
c.add("java");
// 遍历
// Object[] toArray():把集合转成数组,可以实现集合的遍历
Object[] objs = c.toArray();
for (int x = 0; x < objs.length; x++) {
// System.out.println(objs[x]);
// 元素是字符串,获取到元素的的同时,还想知道元素的长度。
// System.out.println(objs[x] + "---" + objs[x].length());
// 上面的实现不了,原因是Object中没有length()方法
// 我们要想使用字符串的方法,就必须把元素还原成字符串
// 向下转型
String s = (String) objs[x];
System.out.println(s + "---" + s.length());
}
结果:
hello---5
world---5
java---4对象集合的遍历
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// 创建集合对象
Collection c = new ArrayList();
// 创建学生对象
Student s1 = new Student("花绛沁", 27);
Student s2 = new Student("花锦瑟", 30);
Student s3 = new Student("尹幽妍", 33);
Student s4 = new Student("上官柳丝", 25);
Student s5 = new Student("蝶恋花", 22);
// 把学生添加到集合
c.add(s1);
c.add(s2);
c.add(s3);
c.add(s4);
c.add(s5);
// 把集合转成数组
Object[] objs = c.toArray();
// 遍历数组
for (int x = 0; x < objs.length; x++) {
// System.out.println(objs[x]);
//向下转型
Student s = (Student) objs[x];
System.out.println(s.getName() + "---" + s.getAge());
}
结果:
花绛沁---27
花锦瑟---30
尹幽妍---33
上官柳丝---25
蝶恋花---22
迭代器
Iterator iterator()
:迭代器,集合的专用遍历方式- Object next():获取元素,并移动到下一个位置。
- NoSuchElementException:没有这样的元素,因为你已经找到最后了。
- boolean hasNext():如果仍有元素可以迭代,则返回 true。
基本对象集合的遍历
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// 创建集合对象
Collection c = new ArrayList();
// 创建并添加元素
// String s = "hello";
// c.add(s);
c.add("hello");
c.add("world");
c.add("java");
// Iterator iterator():迭代器,集合的专用遍历方式
Iterator it = c.iterator(); // 实际返回的肯定是子类对象,这里是多态
while (it.hasNext()) {
// System.out.println(it.next());
String s = (String) it.next();
System.out.println(s);
}
结果:
hello
world
java对象集合的遍历
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
35
36
37
38// 创建集合对象
Collection c = new ArrayList();
// 创建学生对象
Student s1 = new Student("花绛沁", 27);
Student s2 = new Student("花锦瑟", 30);
Student s3 = new Student("尹幽妍", 33);
Student s4 = new Student("上官柳丝", 25);
Student s5 = new Student("蝶恋花", 22);
// 把学生添加到集合
c.add(s1);
c.add(s2);
c.add(s3);
c.add(s4);
c.add(s5);
//遍历
Iterator it = c.iterator();
while(it.hasNext()){
Student s = (Student)it.next();
System.out.println(s.getName() + "---" + s.getAge());
}
结果:
花绛沁---27
花锦瑟---30
尹幽妍---33
上官柳丝---25
蝶恋花---22
注意: NoSuchElementException 不要多次使用it.next()方法
System.out.println(((Student) it.next()).getName() +
"---" + ((Student) it.next()).getAge());
结果:
花绛沁---30
尹幽妍---25
Exception in thread "main" java.util.NoSuchElementException
for的注意点
1 | for (int i = 0; i < list.size(); i++) { |
第一种是普通的for循环遍历
第二种是使用迭代器进行遍历
第三种我们一般称之为增强for循环(for each)
可以看到,第三种形式是JAVA提供的语法糖,这里我们剖洗一下,这种增强for循环底层是如何实现的。
- 反编译后:
1
2
3
4Integer i;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
i = (Integer)iterator.next();
}如果在Vector,Collections.synchronizedList使用增强for循环,就必须在外面单独加锁,因为它不是单单一个操作,不是原子性的,如果在遍历的过程中,进行add,remove操作,就会抛出异常。
Collections工具类
- Collections:是针对集合进行操作的工具类,有对集合进行排序和二分查找的方法,都是静态方法,。
- Collection:是单列集合的顶层接口,有子接口List和Set。
成员方法
方法 | 描述 |
---|---|
public static <T> void sort(List<T> list) |
排序 默认情况下是自然顺序。 |
public static <T> int binarySearch(List<?> list,T key) |
二分查找 |
public static <T> T max(Collection<?> coll) |
最大值 |
public static void reverse(List<?> list) |
反转 |
public static void shuffle(List<?> list) |
随机置换 |
static class SynchronizedList<E> |
将非安全集合包装成一个线程安全的 |
sort(集合,比较器) | 自定义排序方法 |
min(list) | 集合中的最小元素 |
frequency(list,e) | 查找参数元素e在集合元素中出现的次数,不存在为0 |
fill (list,e) | 用元素e填充list |
代码测试
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
35
36
37
38
39
40public static void main(String[] args) {
List<String> list = new ArrayList<>();
//
Collections.addAll(list, "aa","cc","bb");
System.out.println(list);
//自然 升序
Collections.sort(list);
System.out.println(list);
//指定比较器
// Collections.sort(list, (s1,s2)->s2.compareTo(s1));
System.out.println(list);
//查找参数 元素 在集合中 出现的索引 , 前提 升序 排序
// System.out.println(Collections.binarySearch(list, "aaa"));
//集合 中 最小 的 和 最大
System.out.println(Collections.min(list));
System.out.println(Collections.max(list));
//
list.add("aa");
System.out.println(list);
//查找 参数 元素 在集合 中 出现的 次数 ,不存在 0
System.out.println(Collections.frequency(list, "aa"));//2
//对集合元素进行反转
Collections.reverse(list);
System.out.println(list);
//集合元素的洗牌
Collections.shuffle(list);
System.out.println(list);
//集合的填充 ,用 参数 来替换 集合 中的每个元素。
Collections.fill(list, "xxx");
System.out.println(list);
}
比较器排序
static void sort(List list, Comparator<? super T> c)
根据指定的比较器指定的顺序对指定的列表进行排序,如果同时有自然排序和比较器排序,以比较器排序为主
1
2
3
4
5
6
7
8Collections.sort(list, new Comparator<Student>() {
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()): num;
return num2;
}
});
自然排序
对象排序要实现 implements Comparable接口,重写compareTo 方法
1
2
3
4
5
6
public int compareTo(Student s) {
int num = this.age - s.age;
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
模拟斗地主
思路:
1
2
3
4
5
6
7
8A:创建一个HashMap集合
B:创建一个ArrayList集合
C:创建花色数组和点数数组
D:从0开始往HashMap里面存储编号,并存储对应的牌
同时往ArrayList里面存储编号即可。
E:洗牌(洗的是编号)
F:发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收)
G:看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)代码如下:
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74public static void main(String[] args) {
// 创建一个HashMap集合
HashMap<Integer, String> hm = new HashMap<Integer, String>();
// 创建一个ArrayList集合
ArrayList<Integer> array = new ArrayList<Integer>();
// 创建花色数组和点数数组
// 定义一个花色数组
String[] colors = { "♠", "♥", "♣", "♦" };
// 定义一个点数数组
String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
"K", "A", "2", };
// 从0开始往HashMap里面存储编号,并存储对应的牌,同时往ArrayList里面存储编号即可。
int index = 0;
for (String number : numbers) {
for (String color : colors) {
String poker = color.concat(number);
hm.put(index, poker);
array.add(index);
index++;
}
}
hm.put(index, "小王");
array.add(index);
index++;
hm.put(index, "大王");
array.add(index);
// 洗牌(洗的是编号)
Collections.shuffle(array);
// 发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收)
TreeSet<Integer> fengQingYang = new TreeSet<Integer>();
TreeSet<Integer> linQingXia = new TreeSet<Integer>();
TreeSet<Integer> liuYi = new TreeSet<Integer>();
TreeSet<Integer> diPai = new TreeSet<Integer>();
for (int x = 0; x < array.size(); x++) {
if (x >= array.size() - 3) {
diPai.add(array.get(x));
} else if (x % 3 == 0) {
fengQingYang.add(array.get(x));
} else if (x % 3 == 1) {
linQingXia.add(array.get(x));
} else if (x % 3 == 2) {
liuYi.add(array.get(x));
}
}
// 看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
lookPoker("张三", fengQingYang, hm);
lookPoker("李四", linQingXia, hm);
lookPoker("王五", liuYi, hm);
lookPoker("底牌", diPai, hm);
}
// 写看牌的功能
public static void lookPoker(String name, TreeSet<Integer> ts,
HashMap<Integer, String> hm) {
System.out.print(name + "的牌是:");
for (Integer key : ts) {
String value = hm.get(key);
System.out.print(value + " ");
}
System.out.println();
}
张三的牌是:♠A ♦A ♣3 ♠4 ♦4 ♥5 ♦6 ♠7 ♥7 ♣8 ♥9 ♣9 ♥J ♦J ♥Q ♠K 小王
李四的牌是:♥A ♣A ♥2 ♦2 ♥3 ♦3 ♥4 ♣4 ♣5 ♦5 ♣7 ♦7 ♥8 ♦9 ♥10 ♦10 ♣Q
王五的牌是:♠2 ♣2 ♠3 ♠6 ♥6 ♣6 ♠8 ♦8 ♠9 ♣10 ♠J ♠Q ♦Q ♥K ♣K ♦K 大王
底牌的牌是:♠5 ♠10 ♣J
SynchronizedList
类具体代码
代码
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
final List<E> list;
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return list.hashCode();}
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public int indexOf(Object o) {
synchronized (mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized (mutex) {return list.lastIndexOf(o);}
}
public boolean addAll(int index, Collection<? extends E> c) {
synchronized (mutex) {return list.addAll(index, c);}
}
public ListIterator<E> listIterator() {
return list.listIterator(); // Must be manually synched by user
}
public ListIterator<E> listIterator(int index) {
return list.listIterator(index); // Must be manually synched by user
}
public List<E> subList(int fromIndex, int toIndex) {
synchronized (mutex) {
return new SynchronizedList<>(list.subList(fromIndex, toIndex),
mutex);
}
}
public void replaceAll(UnaryOperator<E> operator) {
synchronized (mutex) {list.replaceAll(operator);}
}
public void sort(Comparator<? super E> c) {
synchronized (mutex) {list.sort(c);}
}
private Object readResolve() {
return (list instanceof RandomAccess
? new SynchronizedRandomAccessList<>(list)
: this);
}
}
使用方式
官方文档就是下面的使用方式
1
2
3
4
5
6
7CopyList list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
既然封装类内部已经加了对象锁,为什么外部还要加一层对象锁?
看源码可知,Collections.synchronizedList中很多方法,比如equals,hasCode,get,set,add,remove,indexOf,lastIndexOf……都添加了锁,
但是List中
CopyIterator<E> iterator();
这个方法没有加锁,不是线程安全的,所以如果要遍历,还是必须要在外面加一层锁。使用Iterator迭代器的话,似乎也没必要用Collections.synchronizedList的方法来包装了——反正都是必须要使用Synchronized代码块包起来的。
所以总的来说,Collections.synchronizedList这种做法,适合不需要使用Iterator、对性能要求也不高的情况。
SynchronizedList和Vector最主要的区别
- Vector扩容为原来的2倍长度,ArrayList扩容为原来1.5倍
- SynchronizedList有很好的扩展和兼容功能。他可以将所有的List的子类转成线程安全的类。
- 使用SynchronizedList的时候,进行遍历时要手动进行同步处理 。
- SynchronizedList可以指定锁定的对象。
**
总结
Java带有一组接口和类,使得操作成组的对象更为容易,这就是集合框架
集合框架主要用到的是Collection接口,Collection是将其他对象组织到一起的一个对象,提供了一种方法来存储、访问和操作其元素
List、Set和Queue是Collection的三个主要的子接口。此外,还有一个Map接口用于存储键值对
接口 描述 Collection Collection是最基本的集合接口,一个 Collection 代表一组Object,Java不提供直接继承自Collection的类,只提供继承于它的子接口 List List接口是一个有序的Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引来访问List中的元素,而且允许有相同的元素 Set Set具有与Collection完全一样的接口,只是行为上不同,Set不保存重复的元素 Queue Queue通过先进先出的方式来存储元素,即当获取元素时,最先获得的元素是最先添加的元素,依次递推 SortedSet 继承于Set保存有序的集合 Map 将唯一的键映射到值 Map.Entry 描述在一个Map中的一个元素(键/值对),是一个Map的内部类 SortedMap 继承于Map,使Key保持在升序排列