前面重点说的差不多了,今天讲讲集合中关于Connection接口中的常用List子接口和Set子接口吧,权当自己复习过程了,自己在梳理一遍,有空闲读者也试试这种方式,整个知识的体系架构就在脑海里了存着了,今天先说到这那么开始今天的主题吧。
Connection
1、Connection接口以及常用子接口的概述。
|---Collection接口:存储的是一个一个的数据
|----List接口:存储的是序的、可重复的数据 ----"动态"数组
|---ArrayList、LinkedList、Vector
|----Set接口:存储的是无序的、不可重复的数据 ----高中的"集合"
|---HashSet、LinkedHashSet、TreeSet简单给个图示吧:
2.Collection接口常用方法:
add(Object obj); //添加一个对象
addAll(Collection coll1); //添加一个Collection
size(); //集合大小
isEmpty(); //集合是否为空
clear(); //清空集合
constains(Object obj);constainsAll(Collection coll1); //是否包含一个对象/collection
remove(Object obj); //删除一个对象
removeAll(Colllection coll1); //删除一个collection
equals(Object obj);hashCode();toArray(); //常用就不说了
iterator(); //获取迭代器3.Collection集合与数组间的转换
//toArray():集合转换为数组 Object[] array = coll.toArray(); System.out.println(Arrays.toString(array)); //Arrays的asList(T ... t):数组转换为集合 Collection list1 = Arrays.asList(new String[]{"AA","BB","CC"}); System.out.println(list1);
注意:向Collection中添加的对象,要求对象所属的类一定要重写equals()。
Iterator
1.遍历Collection的两种方式:
方式一:使用迭代器:Iterator
方式二:增强for循环:foreach
2.java.utils包下定义的迭代器接口:Iterator
2.1说明:Iterator对象称为迭代器(设计模式的一种)
2.2作用:主要用于遍历 Collection 集合中的元素。
2.3如何获取实例:
//iterator():返回一个迭代器的实例
2.4常用方法://hasNext():判断是否还下一个元素 //next():①指针下移 ②将下移以后集合位置上的元素返回
2.5举例:
Iterator iterator = coll.iterator(); //hasNext():判断是否还下一个元素 while(iterator.hasNext()){ //next():①指针下移 ②将下移以后集合位置上的元素返回 System.out.println(iterator.next()); }
2.6图示说明:
List接口(Collection子接口)
1. 存储的数据特点:存储的是有序的、可重复的数据 ----"动态"数组
2. 常用方法:
增:add(Object obj)
删:remove(Object obj) / remove(int index)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
长度:size()
遍历:iterator() / 增强for / 一般的for3. 常用实现类:
|----List接口:存储的是序的、可重复的数据 ----"动态"数组
|---ArrayList:主要实现类;线程不安全的,效率高;底层使用Object[]存储。
(Collections工具中提供了将ArrayList转换为线程安全的方法)
|---LinkedList:对于频繁的插入和删除操作,建议使用此类,因为效率高;底层使用双向链表实现。
|---Vector:古老实现类;线程安全的,效率低;底层使用Object[]存储。4、源码剖析(***)
ArrayList的源码:
jdk7: 当添加第11个元素时,需要考虑扩容:默认扩容为原来的1.5倍,同时需要将原有数组中的数据拷贝到新的数组中。
List list = new ArrayList();//elementData = new Object[10]; list.add(1);//elementData[0] = 1;
jdk8:当我们添加第11个元素时,需要考虑扩容:默认扩容为原来的1.5倍,同时需要将原有数组中的数据拷贝到新的数组中。
List list = new ArrayList();//elementData = {} list.add(1);//此时才创建了长度为10的Object数组,同时将元素添加到索引为0的数组位置。
所以建议使用带参数的构造器,指明底层数组的长度。避免了不必要的扩容和数组元素的复制。
比如:ArrayList list = new ArrayList(30);Vector的源码分析:
jdk7、8:(太古老,不常用)
List list = new Vector();//elementData = new Object[10]; list.add(1);//elementData[0] = 1;
new Vector():底层创建了长度为10的数组
当添加数据到底层数组中,发现数组长度不够时,默认扩容为原来的两倍。LinkedList的源码分析:
LinkedList list = new LinkedList();//底层用链表实现,不用考虑扩容问题 list.add(1);//在底层会将1封装在Node对象中。 Node声明为: private static class Node<E> { E item; Node<E> next; Node<E> prev; }
三者的使用:
在大量的插入、删除时用LinkedList时效率较高,在查询修改时用ArrayList时效率较高。也就是它们底层实现的区别啦,也就是数组与链表的区别。这个我在链表那篇文章有写的。
Set接口(Collection子接口)
1. 存储的数据特点:
存储的是无序的、不可重复的数据。①无序性:不等同于随机性。 人认为:"添加的顺序与遍历的顺序不一致,则称为无序性!"。这个观点是错误的。所谓的无序性,指的是添加数据时,不是依次紧密排列的。
②不可重复性:添加到Set中的元素是不可重复的。 参考标准:需要调用元素所在类的equals()。
2. 元素添加过程
向Set中添加元素a,首先调用元素a所在类的hashCode()方法,计算此对象a的哈希值1,哈希值1经过某种算法以后得到哈希值2.
此哈希值2经过某种算法,得到其在底层数组中存储的索引位置i。判断数组索引位置i上,是否元素。
-->如果索引i位置上没元素:此元素a直接添加成功 ----情况1
-->如果索引i位置上元素b:判断元素a和元素b哈希值2是否相等。
-->如果哈希值不相等:元素a添加成功 ----情况2
-->如果哈希值相等,此时调用元素a所在类的equals(),判断返回值。
-->返回false:元素a添加成功 ----情况3
-->返回true:元素a添加失败Set在开发中的主要作用:用来去除重复数据。
3. 常用方法
Set在继承Collection基础上,没额外的定义方法。
4. 常用实现类:
|---HashSet:主要实现类;底层使用的数组结构
|---LinkedHashSet:HashSet的子类;底层使用的数组结构+链表;
可以照添加元素的顺序实现遍历
|---TreeSet:底层使用的红黑树实现的;实现照添加的元素的指定的属性实现遍历5. 存储对象所在类的要求:
- 向HashSet\LinkedHashSet中添加的元素,要求其所在的类一定要重写equals()和hashCode()。
- 向TreeSet中添加的元素,要求对象一定指明是自然排序还是定制排序。需要重写compareTo()或compare()方法。这两个方法就是判断两个对象是否相同的唯一标准。
6. TreeSet的使用:
6.1 使用说明:
①向TreeSet中添加的数据,必须是同一个类创建的对象。
②向TreeSet中添加的数据,需要指明排序方式:①自然排序 ②定制排序
③TreeSet中判断两个元素是否相同的标准不是考虑所在的的hashCode()和equals()了。
而是根据排序方式中重写的compareTo() 或 compare()方法的返回值进行判断。
如果方法的返回值为0,则认为两个对象相同。6.2 常用的排序方式:(这个有讲了,在java常用类有讲过这两者的使用以及区别)
①自然排序
②定制排序