您的位置:首页 > 其它

HashSet,TreeSet,LinkedHashSet 的用法和区别

2017-08-29 18:44 369 查看
Set接口

Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。

使用add()方法添加时,允许添加不会报错,但是在set中只会存在一个元素。

Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不 会接受这两个对象。

HashSet
HashSet有以下特点
不能保证元素的排列顺序,顺序有可能发生变化
不是同步的
集合元素可以是null,但只能放入一个null
当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。
简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相 等
注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对 象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。



LinkedHashSet

LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。

LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
TreeSet类

TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。

TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0

自然排序

自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。

Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。

obj1.compareTo(obj2)方法如果返回0,则说明被比较的两个对象相等,如果返回一个正数,则表明obj1大于obj2,如果是 负数,则表明obj1小于obj2。

如果我们将两个对象的equals方法总是返回true,则这两个对象的compareTo方法返回应该返回0

定制排序

自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现 int compare(T o1,T o2)方法

--------------------------分割线------------------------------

测试插入效率

package Collection_deep;

import java.util.HashSet;

import java.util.Iterator;

import java.util.LinkedHashSet;

import java.util.Random;

import java.util.Set;

import java.util.TreeSet;

public class RepeatSet {
static Set addSet(Set s){
long start = System.currentTimeMillis();
for(int i=0;i<10000;i++){
Random r = new Random();
s.add(r.nextInt(10000));
}
long ContinuedTime = System.currentTimeMillis()-start;
System.out.println("执行插入10000次操作:"+s.getClass().getSimpleName()+"花费时长为:"+ContinuedTime);
long startRead = System.currentTimeMillis();
Iterator i = s.iterator();
while(i.hasNext()){
i.next();
}
long readTime = System.currentTimeMillis()-startRead;;
System.out.println("执行读取10000次操作:"+s.getClass().getSimpleName()+"花费时长为:"+readTime);

return s;


public static void main(String[] args) {
System.out.println("---------------");
addSet(new HashSet());
System.out.println("---------------");
addSet(new TreeSet());
System.out.println("---------------");
addSet(new LinkedHashSet());
System.out.println("---------------");
}

}

测试结果

通过结果可以明显看到,在执行插入操作时,LinkedHashSet和HashSet执行速度相对较快,而TreeSet的速度为最慢;

这里面需要说明的是,

hashset实现Set接口,查询速度快,为快速查找而设计的Set,存入hashSet元素必须定义hashCode;

linkedSet也实现Set接口,具有hashSet的查询速度,而linkedlist是保持次序的set,内部使用链表来维护元素的插入顺序。

treeSet 实现的接口为NavigableSet,同时NavigableSet又继承子SortedSet,所以treeSet底层为树结构,可以保证插入元素按顺序排列。

-----------------------------分割线--------------------------------

这里需要注明的是,

SortedSet是个接口,它里面的(只有TreeSet这一个实现可用)中的元素一定是有序的。

 保证迭代器按照元素递增顺序遍历的集合,可以按照元素的自然顺序(参见 Comparable)进行排序, 或者按照创建有序集合时提供的 Comparator进行排序。

方法测试代码:

package Collection_deep;

import java.util.Random;

import java.util.SortedSet;

import java.util.TreeSet;

public class SortSetDemo {

public static void main(String[] args) {
SortedSet<Integer>  ss = new TreeSet<Integer>();
for(int i = 0;i<1000;i++){
int j = new Random().nextInt(10);
ss.add(j);
}
System.out.println(ss);
System.out.println(ss.subSet(0, 10));//截取set  包含0开始 不包含第10位结束
System.out.println(ss.first());//set的第一个元素
System.out.println(ss.last());//set的最后一个元素
System.out.println(ss.headSet(10));//从第一位到第10为元素
System.out.println(ss.tailSet(10));//从第10位(包含第10位元素)到最后
System.out.println(ss.comparator());//返回NULL表示以自然排序,否则返回当前set使用的Co'm'pa'rator
}

}

运行结果:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息