您的位置:首页 > 编程语言 > Java开发

[学习笔记]Java集合框架之Set集合

2014-12-14 22:45 477 查看


Set集合


特点

Set集合中的元素是唯一的,不可重复(取决于hashCode和equals方法),也就是说具有唯一性。
Set集合中元素不保证存取顺序,并不存在索引。

继承关系

Collection

|--Set:元素唯一,不保证存取顺序,只可以用迭代器获取元素。

|--HashSet:哈希表结构,非线程安全,查询速度较快。元素唯一性取决于hashCode和equals方法。

|--LinkedHashSet:带有双向链表的哈希表结构,非线程安全,保持存取顺序,保持了查询速度较快特点。

|--TreeSet:平衡排序二叉树(红黑树)结构,非线程安全,按自然排序或比较器存入元素以保证元素有序。

元素唯一性取决于ComparaTo方法或Comparator比较器。

常用方法

Set集合的方法和Collection集合的方法几乎一致。


HashSet集合


特点

元素具有唯一性,取决于hashCode和equals方法。
元素不保证存取顺序。
由于采用哈希表数据结构,所以查询较快。
与List一样,建议使用多态的方式,创建HashSet集合并使用Set接口方法。

关于hashCode和equals方法

在以哈希表为数据结构的容器中,其存放地址取决于hashCode方法计算的值,如果hashCode的值相同,则用equals方法判断是否相同,如果都相同则判定为相同元素。
在以哈希表为数据结构的容器使用过程中,已经加入的元素不可以变更hashCode方法所依赖的域的值,否则会导致元素hashCode值已变化,但是其在容器中的位置却没有变化,后果是接下来的remove等操作将因为无法找到该元素而移除失败,进一步导致内存泄露。


元素唯一性示例

Person.java

packagebean;publicclassPerson{privateStringname;privateintage;publicPerson(Stringname,intage){super();this.name=name;this.age=age;}@OverridepublicinthashCode(){finalintprime=31;intresult=1;result=prime*result+age;result=prime*result+((name==null)?0:name.hashCode());returnresult;}@Overridepublicbooleanequals(Objectobj){if(this==obj)returntrue;if(obj==null)returnfalse;if(getClass()!=obj.getClass())returnfalse;Personother=(Person)obj;if(age!=other.age)returnfalse;if(name==null){if(other.name!=null)returnfalse;}elseif(!name.equals(other.name))returnfalse;returntrue;}@OverridepublicStringtoString(){return"Person[name="+name+",age="+age+"]";}}


HashSetDemo.java

packageCollection;importjava.util.HashSet;importjava.util.Iterator;importjava.util.Set;importbean.Person;publicclassHashSetDemo{publicstaticvoidmain(String[]args){//Set集合保证元素唯一性。Set<String>set=newHashSet<String>();set.add("Java1");set.add("Java2");set.add("Java1");set.add("Java1");set.add("Java2");for(Iterator<String>it=set.iterator();it.hasNext();){System.out.println(it.next());}System.out.println("-------------------");//Set集合存储自定义类时,建议该类重写hashCode和equals方法,这是保证元素唯一性的前提,一般还会重写toString方法。Set<Person>setObj=newHashSet<Person>();setObj.add(newPerson("Jacob",25));setObj.add(newPerson("Meteor",23));setObj.add(newPerson("Tom",26));setObj.add(newPerson("Llllin",27));setObj.add(newPerson("Jacob",24));for(Iterator<Person>it=setObj.iterator();it.hasNext();){System.out.println(it.next());}}}


运行结果

[align=left]Java2[/align]
[align=left]Java1[/align]
[align=left]-------------------[/align]
[align=left]Person[name=Jacob,age=25][/align]
[align=left]Person[name=Tom,age=26][/align]
[align=left]Person[name=Jacob,age=24][/align]
[align=left]Person[name=Meteor,age=23][/align]
[align=left]Person[name=Llllin,age=27][/align]

不保证元素存取顺序示例

packageCollection;importjava.util.HashSet;importjava.util.Iterator;importjava.util.Set;publicclassHashSetDemo{publicstaticvoidmain(String[]args){//Set集合不保证存取顺序。Set<String>set=newHashSet<String>();set.add("Java1");set.add("Java2");set.add("Java3");set.add("Java4");set.add("Java5");for(Iterator<String>it=set.iterator();it.hasNext();){System.out.println(it.next());}}}


运行结果

[align=left]Java2[/align]
[align=left]Java3[/align]
[align=left]Java4[/align]
[align=left]Java5[/align]
[align=left]Java1[/align]

比较器

[align=left]1.Comparable接口[/align]
[align=left]自定义类如果实现该接口,那么重写该接口唯一的方法comparaTo(E),可以让该类具有可比较性。[/align]

[align=left]2.Comparator接口[/align]
[align=left]实现该接口的类被称之为比较器,一般只具有一个方法,就是重写的这个接口的compara(Eo1,Eo2)方法,实现两个对象之间的比较。[/align]

案例

[align=left]获取Set集合中元素的最大值(要求元素具有可比性)。[/align]
[align=left]ComparatorByLength.java[/align]

packagecomparator;importjava.util.Comparator;publicclassComparatorByLengthimplementsComparator<String>{@Overridepublicintcompare(Strings1,Strings2){intresult=s1.length()-s2.length();returnresult==0?s1.compareTo(s2):result;}}


[align=left]HashSetTest.java[/align]

packagecollection.set;importjava.util.Collections;importjava.util.HashSet;importjava.util.Iterator;importjava.util.Set;importcomparator.ComparatorByLength;publicclassHashSetTest{publicstaticvoidmain(String[]args){/**案例:获取集合最大值*/Set<String>set=newHashSet<String>();set.add("Jacob");set.add("Java");set.add("Meteor");set.add("abc");set.add("it&java");set.add("zz");//方法一:使用Collections.max()方法(使用的是自然排序方法)。System.out.println(Collections.max(set));//方法二:使用自然排序System.out.println(getMax(set));//方法三:使用比较器(ComparatorByLength)System.out.println(getMax(set,newComparatorByLength()));}/***使用比较器获取Set集合中的最大值(使用字符串长度比较器)**@paramset*@paramcomparatorByLength*@return*/publicstaticObjectgetMax(Set<String>set,ComparatorByLengthcomparatorByLength){if(comparatorByLength==null){thrownewNullPointerException();}Iterator<String>it=set.iterator();Stringmax=it.next();while(it.hasNext()){Stringobj=it.next();if(comparatorByLength.compare(obj,max)>0){max=obj;}}returnmax;}/***使用自然排序获取Set集合中的最大值。**@paramset*@return*/publicstaticObjectgetMax(Set<String>set){Iterator<String>it=set.iterator();Stringmax=it.next();while(it.hasNext()){Stringcom=it.next();if(com.compareTo(max)>0){max=com;}}returnmax;}}


运行结果

[align=left]zz[/align]
[align=left]zz[/align]
[align=left]it&java[/align]


LinkedHashSet集合

特点

HashSet集合具有的优点LinkedHashSet集合都具有。
LinkedHashSet集合在HashSet查询速度快的前提下,能够保持元素存取顺序。

保持元素存取示例

packagecollection;
importjava.util.HashSet;
importjava.util.Iterator;
importjava.util.LinkedHashSet;
importjava.util.Set;
publicclassSet_LinkedHashSet{
publicstaticvoidmain(String[]args){
/*
*LinkedHashSet可以保持元素存取顺序
*/
Set<String>set1=newHashSet<String>();
Set<String>set2=newLinkedHashSet<String>();
init(set1);
init(set2);
System.out.println("HashSet:");
for(Iterator<String>it=set1.iterator();it.hasNext();){
System.out.println(it.next());
}
System.out.println("LinkedHashSet:");
for(Iterator<String>it=set2.iterator();it.hasNext();){
System.out.println(it.next());
}
}
publicstaticvoidinit(Set<String>set){
set.add("Java1");
set.add("Java2");
set.add("Java3");
set.add("Java4");
set.add("Java5");
}
}


运行结果

[align=left]HashSet:[/align]
[align=left]Java2[/align]
[align=left]Java3[/align]
[align=left]Java4[/align]
[align=left]Java5[/align]
[align=left]Java1[/align]
[align=left]LinkedHashSet:[/align]
[align=left]Java1[/align]
[align=left]Java2[/align]
[align=left]Java3[/align]
[align=left]Java4[/align]
[align=left]Java5[/align]


TreeSet集合

特点

元素具有唯一性,取决于Comparable.comparaTo方法或比较器Comparator。
元素不保证存取顺序。
由于采用平衡排序二叉树,所以保存的元素均有序。
与List一样,建议使用多态的方式,创建TreeSet集合并使用Set接口方法。
创建TreeSet集合时,必须保证元素已经实现Comparable接口或者传入比较器Comparator。

示例

[align=left]使用自然排序和比较器加入TreeSet集合进行排序[/align]
[align=left]Person.java[/align]

packagebean;
publicclassPersonimplementsComparable<Person>{
privateStringname;
privateintage;
publicPerson(Stringname,intage){
super();
this.name=name;
this.age=age;
}
publicPerson(){
super();
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
@Override
publicinthashCode(){
finalintprime=31;
intresult=1;
result=prime*result+age;
result=prime*result+((name==null)?0:name.hashCode());
returnresult;
}
@Override
publicbooleanequals(Objectobj){
if(this==obj)returntrue;
if(obj==null)returnfalse;
if(getClass()!=obj.getClass())returnfalse;
Personother=(Person)obj;
if(age!=other.age)returnfalse;
if(name==null){
if(other.name!=null)returnfalse;
}elseif(!name.equals(other.name))returnfalse;
returntrue;
}
@Override
publicStringtoString(){
return"Person[name="+name+",age="+age+"]";
}
@Override
publicintcompareTo(Persono){
intmargin=this.name.compareTo(o.name);
returnmargin==0?this.age-o.age:margin;
}
}
ComparatorByAge.java
packagecomparator;
importjava.util.Comparator;
importbean.Person;
publicclassComparatorByAgeimplementsComparator<Person>{
@Override
publicintcompare(Persono1,Persono2){
intmargin=o1.getAge()-o2.getAge();
returnmargin==0?o1.compareTo(o2):margin;
}
}


[align=left]TreeSetDemo.java[/align]

packagecollection.set;
importjava.util.Collections;
importjava.util.Iterator;
importjava.util.Set;
importjava.util.TreeSet;
importbean.Person;
importcomparator.ComparatorByAge;
importcomparator.ComparatorByLength;
publicclassTreeSetDemo{
publicstaticvoidmain(String[]args){
//使用自然排序将字符串加入TreeSet集合
System.out.println("字符串(自然排序):");
Set<String>set=newTreeSet<String>();
set.add("java");
set.add("linkedhashset");
set.add("awesome");
set.add("zzz");
set.add("treeset");
//元素在添加的时候就已经间接调用compareTo方法进行排序
for(Objectobject:set){
System.out.println(object);
}
//使用比较器将字符串按由长至短加入TreeSet集合
System.out.println("字符串(比较器):");
Set<String>setComparatorByLength=
newTreeSet<String>(Collections.reverseOrder(newComparatorByLength()));
setComparatorByLength.add("java");
setComparatorByLength.add("linkedhashset");
setComparatorByLength.add("awesome");
setComparatorByLength.add("zzz");
setComparatorByLength.add("treeset");
for(Stringstring:setComparatorByLength){
System.out.println(string);
}
//使用自然排序将自定义类加入TreeSet集合
System.out.println("自定义类(自然排序):");
Set<Person>setObj=newTreeSet<Person>();
setObj.add(newPerson("jacob",25));
setObj.add(newPerson("meteor",23));
setObj.add(newPerson("kitty",22));
setObj.add(newPerson("tom",26));
for(Iterator<Person>it=setObj.iterator();it.hasNext();){
System.out.println(it.next());
}
//使用比较器将自定义类加入TreeSet集合
System.out.println("自定义类(比较器):");
TreeSet<Person>setObjComparatorByAge=newTreeSet<Person>(newComparatorByAge());
setObjComparatorByAge.add(newPerson("jacob",25));
setObjComparatorByAge.add(newPerson("meteor",23));
setObjComparatorByAge.add(newPerson("kitty",22));
setObjComparatorByAge.add(newPerson("tom",26));
for(Iterator<Person>it=setObjComparatorByAge.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}


运行结果

[align=left]字符串(自然排序):[/align]
[align=left]awesome[/align]
[align=left]java[/align]
[align=left]linkedhashset[/align]
[align=left]treeset[/align]
[align=left]zzz[/align]
[align=left]字符串(比较器):[/align]
[align=left]linkedhashset[/align]
[align=left]treeset[/align]
[align=left]awesome[/align]
[align=left]java[/align]
[align=left]zzz[/align]
[align=left]自定义类(自然排序):[/align]
[align=left]Person[name=jacob,age=25][/align]
[align=left]Person[name=kitty,age=22][/align]
[align=left]Person[name=meteor,age=23][/align]
[align=left]Person[name=tom,age=26][/align]
[align=left]自定义类(比较器):[/align]
[align=left]Person[name=kitty,age=22][/align]
[align=left]Person[name=meteor,age=23][/align]
[align=left]Person[name=jacob,age=25][/align]
[align=left]Person[name=tom,age=26][/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: