Java集合体系总结
2017-07-30 01:26
369 查看
一、集合框架
集合是容纳数据的容器,java常用的集合体系图如下。以集合中是否运行重复元素来分,主要有List和Set接口,List集合中可以有重复元素,Set集合集合中的元素不可重复,Iterator和List Iterator是遍历集合的2个迭代器,Map是存储Key/Value键值对的容器。java集合体系图
二、迭代器
迭代器的用法写在后面,这里说明Iterator和ListIterator的区别:Iterator在遍历一个集合的过程中不能修改集合中的对象,ListIterator可以修改对象
ListIterator从后往前遍历,有hasPrevious()方法,Iterator没有
ListIterator可以在遍历过程中进行添加元素操作,Iterator不能,否则会报
java.util.ConcurrentModificationException异常。
三、List集合
List集合存储不唯一、有序的对象,可以操作角标。3.1 ArrayList
3.1.1内部实现
ArrayList也叫变长数组,数组的长度是固定的,ArrayList可以随着元素的增多长度增加,内部实现为数组。ArrayList在添加元素时首先会判断长度,长度不够时,长度扩展到原来到1.5倍,原数组复制到新数组。3.1.2关键属性
属性 | 取值或结论 |
---|---|
是否允许重复 | 允许 |
是否有序 | 有序 |
是否允许为空 | 允许 |
是否线程安全 | 否 |
使用场景 | 多查询、少增删 |
3.1.3 测试示例
创建一个ArrayList对象,添加5个元素,其中一个为null:arrayList.add("a1"); arrayList.add("a2"); arrayList.add(null); arrayList.add("a3"); arrayList.add("a4"); System.out.println(arrayList);
打印结果:
[a1, a2, null, a3, a4]
使用迭代器for循环方式遍历:
for (Iterator iter=arrayList.iterator();iter.hasNext();){ System.out.println(iter.next()); }
使用迭代器while循环方式遍历:
Iterator iter=arrayList.iterator(); while (iter.hasNext()){ System.out.println(iter.next()); }
存储自定义对象:
public class Boy { private String name; private int age; //省略setter、getter、构造器和toString()方法 }
添加Boy对象到ArrayList中并打印:
ArrayList<Boy> boys=new ArrayList<>(); Boy b1=new Boy("Tom",12); Boy b2=new Boy("Jack",11); Boy b3=new Boy("Mike",15); boys.add(b1); boys.add(b2); boys.add(b3); System.out.println(boys); Iterator<Boy> iter=boys.iterator(); while (iter.hasNext()){ Boy b=iter.next(); System.out.println(b.getName()+"----"+b.getAge()); }
结果:
[Boy{name='Tom', age=12}, Boy{name='Jack', age=11}, Boy{name='Mike', age=15}] Tom----12 Jack----11 Mike----15
3.1.4 转成线程安全
非线程安全的ArrayListArrayList<String> arrayList = new ArrayList();
线程安全的ArrayList
List arrayList =Collections.synchronizedList(new ArrayList<String>()) ;
3.1.5 常用方法
clear():移除列表中的所有元素contains(Object o): 包含指定元素
get(int index):返回列表中指定位置上的元素
indexOf(Object o): 返回列表中首次出现指定元素的索引,如果列表不包含,则返回-1
isEmpty():列表为空返回true
lastIndexOf(Object o):返回列表中最后一次出现指定元素的索引,如果列表不包含元素则返回-1
remove(int index):移除列表中指定位置的元素
remove(Object o):移除列表中首次出现的指定元素
removeRange(int fromIndex,int toIndex):移除列表中索引在fromIndex(包括)和toIndex(不包括)之间的所有元素。
size():返回集合的元素个数
set(int index,E element):修改指定位置上的元素
toArray():按顺序返回包含此列表中所有元素的数组
3.2 LinkedList
3.2.1内部实现
内部实现为双向链表,删除和增加速度快,查找速度慢。3.2.2关键属性
属性 | 取值或结论 |
---|---|
是否允许重复 | 允许 |
是否有序 | 有序 |
是否允许为空 | 允许 |
是否线程安全 | 否 |
使用场景 | 多增删、少查询 |
3.2.3 测试示例
LinkedList当作FIFO的队列使用,也就是常用的add方法添加元素:LinkedList quene=new LinkedList(); quene.add("a"); quene.add("b"); quene.add("c"); quene.add("d"); System.out.println("打印队列:"+quene); System.out.println("获取队头:"+quene.getFirst()); System.out.println("获取队尾:"+quene.getLast()); System.out.println("移除队头:"+quene.pop()); System.out.println("移除队头之后的队列:"+quene);
打印结果:
打印队列:[a, b, c, d] 获取队头:a 获取队尾:d 移除队头:a 移除队头之后的队列:[b, c, d]
LinkedList当作FILO的栈使用:
LinkedList stack = new LinkedList(); stack.push("1"); stack.push("2"); stack.push("3"); stack.push("4"); System.out.println("打印栈:"+stack); System.out.println("获取栈顶元素:"+stack.peek()); System.out.println("打印栈:"+stack); System.out.println("取出栈顶元素:"+stack.pop()); System.out.println("打印栈:"+stack);
打印结果:
打印栈:[4, 3, 2, 1] 获取栈顶元素:4 打印栈:[4, 3, 2, 1] 取出栈顶元素:4 打印栈:[3, 2, 1]
除了ArrayList中包含的基本方法以为,LinkedList中多了getFirst()、getLast()、addFirst()、addLast()、peek()、peekFirst()、peekLast()、removeFirst()、removeLast()等方法。
3.2.4 转成线程安全
List<Integer> linkedList=Collections.synchronizedList(new LinkedList<Integer>());
3.3 Vector
Vector内部是数组结构,线程安全,速度较慢,几乎不用。四、Set集合
Set集合中的元素唯一、无序,没有角标。4.1HashSet
4.1.1内部实现
内部结构是哈希表,对象存入HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,确保set中没有存储相同的对象。判断两个元素是否相同,首先通过hashCode()方法判断的是2个元素的哈希值是否相同,再根据equals()方法判断值是否相同,只有2者都相同才是统一元素。4.1.2 基本属性
属性 | 取值或结论 |
---|---|
是否允许重复 | 不允许 |
是否有序 | 无序 |
是否允许为空 | 允许(只有一个null) |
是否线程安全 | 否 |
使用场景 | 对象不重复和需要快速查找的场景 |
4.1.3 测试示例
HashSet<String> hashSet=new HashSet(); hashSet.add("abc"); hashSet.add("张三"); hashSet.add("李四"); hashSet.add("tim"); hashSet.add(null); hashSet.add(null); System.out.println("HashSet 大小:"+hashSet.size()); Iterator iter=hashSet.iterator(); while (iter.hasNext()){ System.out.println(iter.next()); }
打印结果:
HashSet 大小:5 null 李四 张三 abc tim
添加自定义对象,仍然添加Boy类中的对象
Boy b1=new Boy("神乐",12); Boy b2=new Boy("神乐",12); HashSet<Boy> boys=new HashSet<>(); boys.add(b1); boys.add(b2); System.out.println(boys);
结果:
[Boy{name='神乐', age=12}, Boy{name='神乐', age=12}]
这时候b1和b2其实是一个对象,在Boy类中重写hashCode()和equals()方法:
public class Boy { private String name; private int age; //省略setter、getter、构造器和toString()方法 @Override public int hashCode() { return name.hashCode()+age; } @Override public boolean equals(Object obj) { if (this==obj) return true; if (!(obj instanceof Boy)) throw new ClassCastException("类型错误"); Boy boy=(Boy) obj; return this.name.equals(boy.name)&&(this.age==boy.age); } }
重写equals和hashCode方法以后,上述集合中就会只添加一个对象:
[Boy{name='神乐', age=12}]
4.1.4 转成线程安全
Set<String> hSet=Collections.synchronizedSet(new HashSet<String>());
4.1.5 唯一且有序
LinkedHashSet集合中都元素唯一且有序,这里都有序是指添加顺序。LinkedHashSet<String> lHashSet= new LinkedHashSet<String>(); lHashSet.add("abc"); lHashSet.add("张三"); lHashSet.add("李四"); lHashSet.add("tim"); lHashSet.add(null); iter=lHashSet.iterator(); while (iter.hasNext()){ System.out.println(iter.next()); }
打印结果:
abc 张三 李四 tim null
4.2 TreeSet
4.2.1 内部实现
TreeSet内部实现为二叉树,可以对元素进行排序4.2.2 基本属性
属性 | 取值或结论 |
---|---|
是否允许重复 | 不允许 |
是否有序 | 无序 |
是否允许为空 | 允许(只有一个null) |
是否线程安全 | 否 |
使用场景 | 去重且排序 |
4.2.3 测试示例
Boy b1=new Boy("定春",16); Boy b2=new Boy("神乐",12); Boy b3=new Boy("桑巴",13); TreeSet<Boy> treeSet=new TreeSet<>(new Comparator<Boy>() { @Override public int compare(Boy o1, Boy o2) { return o1.getAge()-o2.getAge(); } }); treeSet.add(b1); treeSet.add(b2); treeSet.add(b3); System.out.println(treeSet);
打印结果:
[Boy{name='神乐', age=12}, Boy{name='桑巴', age=13}, Boy{name='定春', age=16}]
4.2.4 转成线程安全
TreeSet<Boy> treeSet=new TreeSet<>(new Comparator<Boy>() { @Override public int compare(Boy o1, Boy o2) { return o1.getAge()-o2.getAge(); } }); Set<Boy> treeSet1=Collections.synchronizedSet(treeSet);
五、Map集合
Map只存储的是键值对,Key必须唯一且不为空,key允许为null。5.1HashMap
5.1.1基本属性
属性 | 取值或结论 |
---|---|
是否允许重复 | key重复会被覆盖,value可重复 |
是否有序 | 无序 |
是否允许为空 | key和value都允许为空 |
是否线程安全 | 否 |
5.1.2 测试示例
词频统计:String[] arr={"Hadoop","Lucene","ES","ES","ES","Hadoop","Java","JS"}; //TreeMap<String,Integer> map=new TreeMap<>(); HashMap<String,Integer> map=new HashMap<>(); for (String str:arr){ if (map.containsKey(str)){ map.put(str,map.get(str)+1); }else{ map.put(str,1); } } Set<String> keys=map.keySet(); Iterator<String> iter=keys.iterator(); while (iter.hasNext()){ String str=iter.next(); System.out.println(str+"---"+map.get(str)); }
打印结果:
Java---1 Hadoop---2 JS---1 Lucene---1 ES---3
如果想按value排序,可以改成TreeMap();
六、性能对比
ArrayList遍历性能对比
ArrayList的遍历可以用一般for循环、foreach循环、Iterator迭代器三种方式实现,为了测试它们的性能,先创建一个ArrayList对象,添加5万个字符串:ArrayList<String > a = new ArrayList(); for (int i = 0; i < 60000; i++) { a.add(""+i); }
for 循环打印并记录耗时:
long start = System.currentTimeMillis(); for (int i = 0; i < a.size(); i++) { System.out.print(a.get(i)); } long end = System.currentTimeMillis(); System.out.println("\n下标for循环:" + (end - start));
结果:
150
foreach循环打印并记录耗时:
start = System.currentTimeMillis(); for (String i : a) { System.out.print(i); } end = System.currentTimeMillis(); System.out.println("\nforeach:" + (end - start));
耗时:
95
Iterator循环打印:
start=System.currentTimeMillis(); Iterator iter=a.iterator(); while (iter.hasNext()){ System.out.print(iter.next()); } end=System.currentTimeMillis(); System.out.println("\nIter:"+(end-start));
耗时:
60
结论:一般for 循环最慢、foreach次之、Iterator最快。
另外,Iterator遍历还有另外一种变形方式,效率和while形式一样。
for(Iterator it=a.iterator();it.hasNext();){ System.out.print(it.next()); }
七、参考文章
有些文章总结的很好,列出来供参考学习:Java集合框架
相关文章推荐
- 黑马程序员_java的集合类(对第十四课collection体系集合的总结)
- java_集合体系之List体系总结、应用场景
- 黑马程序员_java的集合类(对第十六课Map体系集合的总结)
- Java集合体系总结 Set、List、Map、Queue
- Java总结系列之集合体系
- java_集合体系之List体系总结、应用场景——07
- Java集合体系总结—Map、Set、List、Queue
- java-集合体系总结
- java_集合体系之List体系总结、应用场景——07
- java集合~List体系总结、ArrayList分析
- Java【集合系列】-04- fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)
- Java集合容器总结
- Java中List、Set和Map等集合总结和介绍
- Java知识总结-Map集合
- Java常用集合体系以及区别
- 黑马程序员_Java_集合总结
- 黑马程序员:Java基础——集合框架之体系概述、共性方法与迭代器
- Java 集合知识总结
- Java 集合体系详解——List体系有序集合
- java集合14--Map总结