java中有几种经常使用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类。 html
public interface Collection<E> extends Iterable<E> {}
它是一个接口,是高度抽象出来的集合,它包含了集合的基本操做:添加、删除、清空、遍历(读取)、是否为空、获取大小、是否保护某元素等等。java
Collection接口的全部子类(直接子类和间接子类)都必须实现2种构造函数:不带参数的构造函数 和 参数为Collection的构造函数。带参数的构造函数,能够用来转换Collection的类型。算法
public interface List<E> extends Collection<E> {}
二、List接口的实现类数据库
(1)ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,能够存储重复元素
(2)LinkedList 底层数据结构是链表,查询慢,增删快,线程不安全,效率高,能够存储重复元素
(3)Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,能够存储重复元素 数组
三、List接口的方法:既然List是继承于Collection接口,它天然就包含了Collection中的所有函数接口;因为List是有序队列,它也额外的有本身的API接口。安全
Arraylist:
优势:ArrayList是实现了基于动态数组的数据结构,由于地址连续,一旦数据存储好了,查询操做效率会比较高(在内存里是连着放的)。
缺点:由于地址连续, ArrayList要移动数据,因此插入和删除操做效率比较低。数据结构
LinkedList:
优势:LinkedList基于链表的数据结构,地址是任意的,因此在开辟内存空间的时候不须要等一个连续的地址,对于新增和删除操做add和remove,LinedList比较占优点。LinkedList 适用于要头尾操做或插入指定位置的场景
缺点:由于LinkedList要移动指针,因此查询操做性能比较低。
适用场景分析:
当须要对数据进行对此访问的状况下选用ArrayList,当须要对数据进行屡次增长删除修改时采用LinkedList。
函数
一、定义:Set是一个继承于Collection的接口,即Set也是集合中的一种。Set是没有重复元素的集合。性能
public interface Set<E> extends Collection<E> {}
二、Set的API和Collection彻底同样。spa
// Set的API abstract boolean add(E object) abstract boolean addAll(Collection<? extends E> collection) abstract void clear() abstract boolean contains(Object object) abstract boolean containsAll(Collection<?> collection) abstract boolean equals(Object object) abstract int hashCode() abstract boolean isEmpty() abstract Iterator<E> iterator() abstract boolean remove(Object object) abstract boolean removeAll(Collection<?> collection) abstract boolean retainAll(Collection<?> collection) abstract int size() abstract <T> T[] toArray(T[] array) abstract Object[] toArray()
三、实现子类
(1)HashSet : 底层数据结构采用哈希表实现,元素无序且惟一,线程不安全,效率高,能够存储null元素,元素的惟一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,若是没有重写这两个方法,则没法保证元素的惟一性。
a、实现惟一性:
存储元素首先会使用hash()算法函数生成一个int类型hashCode散列值,而后已经的所存储的元素的hashCode值比较,若是hashCode不相等,则所存储的两个对象必定不相等,此时存储当前的新的hashCode值处的元素对象;若是hashCode相等,存储元素的对象仍是不必定相等,此时会调用equals()方法判断两个对象的内容是否相等,若是内容相等,那么就是同一个对象,无需存储;若是比较的内容不相等,那么就是不一样的对象,就该存储了,此时就要采用哈希的解决地址冲突算法,在当前hashCode值处相似一个新的链表, 在同一个hashCode值的后面存储存储不一样的对象,这样就保证了元素的惟一性。
b、实现不重复
HashSet也同样他是使用了一种标识来肯定元素的不重复,HashSet用一种算法来保证HashSet中的元素是不重复的, HashSet采用哈希算法,底层用数组存储数据。默认初始化容量16,加载因子0.75。
Object类中的hashCode()的方法是全部子类都会继承这个方法,这个方法会用Hash算法算出一个Hash(哈希)码值返回,HashSet会用Hash码值去和数组长度取模, 模(这个模就是对象要存放在数组中的位置)相同时才会判断数组中的元素和要加入的对象的内容是否相同,若是不一样才会添加进去。
覆盖hashCode()方法的原则:
一、必定要让那些咱们认为相同的对象返回相同的hashCode值
二、尽可能让那些咱们认为不一样的对象返回不一样的hashCode值,不然,就会增长冲突的几率。
三、尽可能的让hashCode值散列开(两值用异或运算可以使结果的范围更广)
c、HashSet的实现
HashSet 的实现比较简单,相关HashSet的操做,基本上都是直接调用底层HashMap的相关方法来完成,咱们应该为保存到HashSet中的对象覆盖hashCode()和equals(),由于再将对象加入到HashSet中时:
首先调用hashCode方法计算出对象的hash值,接着根据此hash值调用HashMap中的hash方法,获得的值& (length-1)获得该对象在hashMap的transient Entry[] table中的保存位置的索引,接着找到数组中该索引位置保存的对象,并调用equals方法比较这两个对象是否相等,若是相等则不添加;
注意:因此要存入HashSet的集合对象中的自定义类必须覆盖hashCode(),equals()两个方法,才能保证集合中元素不重复。在覆盖equals()和hashCode()方法时, 要使相同对象的hashCode()方法返回相同值,覆盖equals()方法再判断其内容。为了保证效率,因此在覆盖hashCode()方法时,也要尽可能使不一样对象尽可能返回不一样的Hash码值。
(2)、LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的惟一性。线程不安全,效率高。
(3)、TreeSet底层数据结构采用二叉树来实现,元素惟一且已经排好序;惟一性一样须要重写hashCode和equals()方法,二叉树结构保证了元素的有序性。根据构造方法不一样,分为天然排序(无参构造)和比较器排序(有参构造)。
天然排序要求元素必须实现Compareable接口,并重写里面的compareTo()方法,元素经过比较返回的int值来判断排序序列,返回0说明两个对象相同,不须要存储;
比较器排须要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;
比较:
一、TreeSet 是二叉树(红黑树的树据结构)实现的,Treeset中的数据是自动排好序的,不容许放入null值;
二、HashSet 是哈希表实现的,HashSet中的数据是无序的,能够放入null,但只能放入一个null,二者中的值都不能重复,就如数据库中惟一约束 ;
三、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码做为标识的,而具备相同内容的String对象,hashcode是同样,因此放入的内容不能重复。可是同一个类的对象能够放入不一样的实例;
适用场景分析:HashSet是基于Hash算法实现的,其性能一般都优于TreeSet。为快速查找而设计的Set,咱们一般都应该使用HashSet,在咱们须要排序的功能时,咱们才使用TreeSet。
(1)、List,Set都是继承自Collection接口;
(2)、List特色:元素有放入顺序,元素可重复 ;Set特色:元素无放入顺序,元素不可重复,重复元素会覆盖掉;
(3)、Set:检索元素效率低下,删除和插入效率高,插入和删除不会引发元素位置改变。
List:和数组相似,List能够动态增加,查找元素效率高,插入删除元素效率低,由于会引发其余元素位置改变。
原文:https://blog.csdn.net/feiyanaffection/article/details/81394745
http://www.cnblogs.com/skywang12345/p/3308513.html