1、为什么要学集合?
- Java是面向对象的,在开发过程中一切皆对象,我们要操作的是对象。
- 在操作多个对象/数据的过程中,我们需要将数据封装存储起来统一管理,所以需要一个容器放对象,就如数组存储数据,但在Java中存储有更方便的容器。
- 数组也可以存储对象等数据,但编写代码时就显得有些臃肿,而且操作不便。
- 可以简单的理解集合是数组的框架,是Java提供给我们操作对象的一个工具,实际上像ArrayList的底层就是数组,也就是说只是封装了以些数组的操作,使得我们开发更方便。
2、集合与数组的区别?
- 区别一:长度
- 数组:长度固定。
- 集合:长度可变。
- 区别二:存储类型的多样化
- 数组:在创建时定好了存储同一种类型元素。
- 集合:可以存储不同类型的元素。(List list = new ArrayList<>();但一般不这样做,这会引起一些操作数据时的类型不一致出现的麻烦)
- 区别三:数据类型的限定
- 数组:可以存储基本类型、也可以存储引用类型。
- 集合:只能存储引用类型(由泛型决定),基本类型可通过装箱成为引用类型存储。
3、有数组为什么不用呢?
- 在实际开发中,当我们存储数据时,数组创建了长度就固定了,当我们需要增加更多的数据时,可以通过新建一个更长的数组然后将旧的数组复制到更长的数组中,新数据加在后面就可以了。
- 试想一下,如果增加的数据不知道多长,又不想一下创建太长的数组浪费资源,也不想每次都写重复上面创建、复制的代码,于是集合的出现解决了该工作。类似增强了的数组。
4、Java容器
- 在实际引用中常用的有:
- List(ArrayList、LinkedList、Vector)
- Set(HashSet、TreeSet、LinkedHashSet)
- Map(HashMap、LinkedHashMap)
- Collection继承体系结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bUUtfLjK-1615520287756)(http://note.youdao.com/yws/public/resource/ac773b4395686236cb47874265ddf7c7/xmlnote/C86CC27B70174343BF78C639A17E0DCE/18464)]
- produces代表该类/接口内部定义了其他的类/接口成员变量(我中有你),如:Collection中有产生Iterator,Map中有产生Collection一样。
- 容器继承简洁图
- 简洁图不过是为了方便记忆,其继承/实现关系存在多层关系,可查看源码查看详细继承/实现。
5、 Collection接口
- 概述:JDK对于Collection不提供任何的直接实现,但提供更加具体的子接口(List/Set)实现。其中有序的(List/LinkedHashSet)、无序的(HashSet)、可重复的(ArrayList/LinkedList)、不可重复的(Set),线程同步(Vector)等实现类。(有序无序指的是以插入时的顺序保存,重复性指的是一个集合中是否只能出现一个同样值的数据)
6、 List接口
- List特点
- List接口下是有序的集合,可以插入重复的值。
- 可以在通过索引修改/访问对应的元素(Set不可以)。
- List的子类
- ArrayList
- LinkedList
- Vector
- List的排序:
- List接口的排序可以通过Collections.sort()来进行定制排序。
- 只需要继承Comparable接口后,重写compareTo()方法。
- 线程不安全解决
-
List list = Collections.synchronizedList(new ArrayList(…)); 线程同步化构造。
-
使用Collections工具的synchronizedList方法。
- 官方使用文档:
List 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中的Iterator iterator();未加锁,所以当用到Iterator时就需要加一层锁。 - 注意:既然Iterator方法没有加锁,由于增强for循环底层使用的也是Iterator,所以当使用增强for循环时同样需要加锁。
名称 默认扩容方式 线程安全 适合的场景 ArrayList 增长50% 不安全 查询多、增删少或者数据量少 LinkedList 增长一倍 不安全 增删多、查询少 Vector 添加一个元素加一个结点 安全 需要严格的线程安全要求 - 官方使用文档:
-
7、Set接口
- Set特点:
- Set是无序、不可重复的(LinkedHashSet除外)。
- 如果有多个null,则不满足单一性了,所以Set只能有一个null。
- Set没有索引,没有带索引的方法,也不能使用普通的for循环遍历。
8、Map
- Map映射的特点:
- Map集合中存储的元素是成对出现的,并且Map的key(键)是只能有一个,value(值)可以重复。
- 存取无序的
- 键和值位置都可以是null,但是键位置只能是一个null
- 键位置是唯一的,底层的数据结构控制键的
- jdk1.8前数据结构是:链表 + 数组 jdk1.8之后是 : 链表 + 数组 + 红黑树
- 阈值(边界值) > 8并且数组长度大于64,才将链表转换为红黑树,变为红黑树的目的是为了高效的查询。
- Map与Collection的区别:
- Map成对存储,Collection单个元素存储。
- Map的键不能重复,值可以重复,Collection中List的元素可以重复,但Collection中的Set是唯一的(深入学习可知,HashSet创建时底层创建的就是HashMap,只不过是把创建出来的HashMap的value值用Object对象填充了,存储时值放在key中,key唯一,因此Set也是唯一的),总的来说,Set集合的实现类是从Map中创建出来的。
- Map集合的数据结构对键有效,与值无关;Collection集合的数据结构对元素有效。