文章迁移(三)

Set接口中的方法和其父类接口Collection一致,我们直接看它的子实现类:HashSet和TreeSet.

HashSet内部数据结构是 哈希表 ,该数据结构有两个要点:一、根据所存对象的hashCode方法(这个方法是上帝类Object的固有方法,如果不被覆盖就走Object的,通过源代码,可以知道这个方法走的是底层nation,所以如果想看效果建议自己建一个类,去覆盖hashCode方法)的返回值(就是那串哈希码)确定存储位置;二、如果两个元素的哈希码相同,会根据对象的equals方法,判断两个对象是否相等,若相等,则不存,不相等会额外分配一个空间来存储元素,这种情况比较特殊和少见,解决办法也不唯一,不要纠结于此,总之HashSet一定确保元素的唯一性。官方文档强调HashSet为基本操作提供了稳定性,原因在于:HashSet在查找元素(无论存储取出或者对元素的其他操作都依赖于查找到这个元素)时的算法是同一个,这个算法的返回值就是元素“应该” 存放的位置,这就保证了存储和取出的一致性,查找元素会很快。显然这个算法需要用到我们之前说的元素自身的hashCode方法和equals方法,前者用于位置的确定,后者主要作为元素唯一性的依据。HashSet自身没有什么特殊的方法,建议自己建一个类,存一些自定义对象试试看,还可以根据需要重写上面反复说的那两个方法,深入理解哈希表数据的结构的特点。

LinkedHashSet是HashSet的子类,它可以提供有序的HashSet集合,即可预知迭代顺序的集合。通过对LinkedHashSet和HashSet的演示操作我们也可以更深入的理解通常所说的有序和无序是怎么回事。

TreeSet内部数据结构是二叉树,TreeSet可以对Set集合中的元素进行排序。涉及到排序,肯定就有比较,TreeSet集合提供了两种排序方式:一、依赖于元素自身的比较方法(compareTo(Object obj))进行排序;二、根据创建Set集合时提供的Comparator(比较器)进行排序。

对于第一种排序方式,对象本身不具备比较方法(Object不具备compareTo方法),需要实现Comparable接口(这个接口强行对实现它的每个类的对象进行整体排序,它有且只有一个方法,就是compareTo方法。常见的String类就继承了这个接口,实现了compareTo方法),进而实现compareTo(Object o)才可以,如果不提供这种排序依据,TreeSet容器存储数据时就会抛异常ClassCastException;第二种排序方式依赖于TreeSet的一个特殊的构造器——TreeSet(Comparator  comparator),根据指定的比较器进行排序。比较器,顾名思义,就是提供比较依据的工具。Comparator是一个接口,我们通过实现该接口并覆盖compare(o1,o2)来创建比较器对象,并根据compare方法提供的比较依据进行排序。

集合至此基本完事儿,接下来会说到泛型和Map映射,在此之前先总结一下集合的使用技巧:

集合使用技巧:

元素唯一吗?

-是的:Set

----需要指定元素的顺序吗?

---需要:TreeSet

---不需要:HashSet

---但是要有序:LinkedHashSet

-不需要:List

----需要频繁增删吗?

---需要:LinkedList

---不需要:ArrayList

前缀名就是该类集合的数据结构:

看到array就要想到数组,就要想到查询快,有角标

看到link就要想到链表,就要想到增删快,就要想    add、get、removeFirst、removeLast等方法

看到hash 就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashCode()和equals().

看到就要想到二叉树,就要想到排序,就要想到两个接口--Comparable和Comparator.

posted @ 2017-12-18 15:35  谈笑千年  阅读(117)  评论(0编辑  收藏  举报