Set集合之HashSet类、LinkedHashSet类、TreeSet类和EnumSet类
2016-11-08 15:16
471 查看
Set集合之HashSet类、LinkedHashSet类、TreeSet类和EnumSet类
(一)HashSet类
前言:HashSet是Set接口的典型实现,绝大多数时候使用Set集合就是使用这个实现类。HashSet按照Hash算法来存储集合中元素,因此具有很好的存取和查找性能。至于HashCode值如何计算,Hash算法的原理以及HashSet的在内存中存储实现读者可以看我这篇博文:equals和HashCode深入理解以及Hash算法原理。在这里我想给读者提醒一下几个对HashSet类使用的小建议:
HashSet的存储原理是先判断对象的HashCode()值,找到存储区域存入但是当HashCode值相同时(我的理解是HashCode值在计算过程中不小心冲突了),equals返回false,则这时候系统会在这个位置采用链式结构来保存多个对象,这时候会导致性能下降。(其实我们这里讲的对象是指对象引用,容器类或者说集合类添加进去的都是同一个引用类型的对象引用,集合中的元素是对象实例化后的对象引用,在内存中保存的是地址)
内存泄露问题:当程序把可变对象添加到HashSet中后,尽量不要去修改该集合元素中参与计算hashCode()、equals()的实例变量,这样将导致对象hashCode值改变,要去访问该对象时找不到。
以下是HashSet使用例子,Set集合存储自定义类时,建议该类重写hashCode和equals方法,这是保证元素唯一性的前提,一般还会重写toString方法。
Person.java package bean; public class Person { private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj ) { if (this == obj) return true ; if (obj == null) return false; if (getClass() != obj.getClass()) return false ; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]" ; } }
HashSetDemo.java
package Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import bean.Person; public class HashSetDemo { public static void main(String[] args) { // Set集合保证元素唯一性。 Set<String> set = new HashSet<String>(); set.add("Java1"); set.add("Java2"); set.add("Java1"); set.add("Java1"); set.add("Java2"); //用迭代器对Set集合进行遍历 for (Iterator<String> it = set.iterator(); it.hasNext();) { System.out.println( it.next()); } System.out.println( "-------------------"); // Set集合存储自定义类时,建议该类重写hashCode和equals方法,这是保证元素唯一性的前提,一般还会重写toString方法。 Set<Person> setObj = new HashSet<Person>(); setObj.add(new Person( "Jacob", 25)); setObj.add(new Person( "Meteor", 23)); setObj.add(new Person( "Tom", 26)); setObj.add(new Person( "Llllin", 27)); setObj.add(new Person( "Jacob", 24)); for (Iterator<Person> it = setObj.iterator(); it.hasNext();) { System.out.println( it.next()); } } }
运行结果
Java2
java1
Person [name=Jacob, age=25]
Person [name=Tom, age=26]
Person [name=Jacob, age=24]
Person [name=Meteor, age=23]
Person [name=Llllin, age=27]
(二)LinkedHashSet集合
HashSet类有一个子类LinkedHashSet,LinkedHashSet集合也是根据hashCode值来决定元素的存储位置,但它同时使用链表来维护元素的次序。LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但是在迭代访问Set里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。
package collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; public class Set_LinkedHashSet { public static void main(String[] args) { /* * LinkedHashSet可以保持元素存取顺序 */ Set<String> set1 = new HashSet<String>(); Set<String> set2 = new LinkedHashSet<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()); } } public static void init(Set<String> set) { set.add("Java1"); set.add("Java2"); set.add("Java3"); set.add("Java4"); set.add("Java5"); } }
运行结果
HashSet:
Java2
Java3
Java4
Java5
Java1
LinkedHashSet:
Java1
Java2
Java3
Java4
Java5
(三)TreeSet集合
TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。从这句话中我们可以看出,添加到TreeSet中的元素(对象的实例)必须实现了Comparable接口或者传入比较器Comparator,具体可以看我们这篇博文[Comparable和Comparator].(http://blog.csdn.net/qq_21688757/article/details/53084282)使用自然排序和比较器加入TreeSet集合进行排序:
package bean; public class Person implements Comparable<Person> { private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge( int age) { this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj ) { if (this == obj) return true ; if (obj == null) return false; if (getClass() != obj.getClass()) return false ; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]" ; } //先按字符串默认排列,若相同再按年龄排列 @Override public int compareTo(Person o) { int margin = this.name.compareTo( o. name); return margin == 0 ? this. age - o. age : margin; } } ComparatorByAge.java package comparator; import java.util.Comparator; import bean.Person; public class ComparatorByAge implements Comparator<Person> { //先按年龄升序排列,若相同在按字符串排列 @Override public int compare(Person o1, Person o2) { int margin = o1.getAge() - o2.getAge(); return margin == 0 ? o1 .compareTo(o2 ) : margin ; } }
TreeSetDemo.java
package collection.set; import java.util.Collections; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import bean.Person; import comparator.ComparatorByAge; import comparator.ComparatorByLength; public class TreeSetDemo { public static void main(String[] args) { // 使用自然排序将字符串加入TreeSet集合 System.out.println( "字符串(自然排序):" ); Set<String> set = new TreeSet<String>(); set.add("java"); set.add("linkedhashset"); set.add("awesome"); set.add("zzz"); set.add("treeset"); // 元素在添加的时候就已经间接调用compareTo方法进行排序 for (Object object : set) { System.out.println( object); } // 使用比较器将字符串按由长至短加入TreeSet集合 System.out.println( "字符串(比较器):" ); Set<String> setComparatorByLength = new TreeSet<String>(Collections. reverseOrder(new ComparatorByLength())); setComparatorByLength.add( "java"); setComparatorByLength.add( "linkedhashset"); setComparatorByLength.add( "awesome"); setComparatorByLength.add( "zzz"); setComparatorByLength.add( "treeset"); for (String string : setComparatorByLength) { System.out.println( string); } // 使用自然排序将自定义类加入TreeSet集合 System.out.println( "自定义类(自然排序):" ); Set<Person> setObj = new TreeSet<Person>(); setObj.add(new Person( "jacob", 25)); setObj.add(new Person( "meteor", 23)); setObj.add(new Person( "kitty", 22)); setObj.add(new Person( "tom", 26)); for (Iterator<Person> it = setObj.iterator(); it.hasNext();) { System.out.println( it.next()); } // 使用比较器将自定义类加入TreeSet集合 System.out.println( "自定义类(比较器):" ); TreeSet<Person> setObjComparatorByAge = new TreeSet<Person>(new ComparatorByAge()); setObjComparatorByAge.add( new Person( "jacob", 25)); setObjComparatorByAge.add( new Person( "meteor", 23)); setObjComparatorByAge.add( new Person( "kitty", 22)); setObjComparatorByAge.add( new Person( "tom", 26)); for (Iterator<Person> it = setObjComparatorByAge.iterator(); it .hasNext();) { System.out.println( it.next()); } } }
运行结果
字符串(自然排序):
awesome
java
linkedhashset
treeset
zzz
字符串(比较器):
linkedhashset
treeset
awesome
java
zzz
自定义类(自然排序):
Person [name=jacob, age=25]
Person [name=kitty, age=22]
Person [name=meteor, age=23]
Person [name=tom, age=26]
自定义类(比较器):
Person [name=kitty, age=22]
Person [name=meteor, age=23]
Person [name=jacob, age=25]
Person [name=tom, age=26]
相关文章推荐
- Set集合,HashSet类,TreeSet类,EnumSet类
- JAVA基础再回首(十七)——Set集合、增强for、HashSet类、LinkedHashSet类、TreeSet类、二叉树、Comparator 排序
- Set集合,HashSet类,TreeSet类,EnumSet类
- Java集合概述、Set集合(HashSet类、LinkedHashSet类、TreeSet类、EnumSet类)
- Java学习之容器上(Collection接口常用方法,Iterator接口,使用foreach循环遍历Collection集合元素,Set集合通用知识(Hashset类,hashcode()与LinkedHashSet类))
- 集合框架源码分析五之LinkedHashMap,LinkedHashSet
- 黑马程序员_学习笔记:9) 集合框架1:Collection(List、Set)、Iterator、List(ArrayList、LinkedList、Vector)
- 集合框架源码分析五之LinkedHashMap,LinkedHashSet
- Java——(四)Collection之Set集合TreeSet类
- 老紫竹JAVA提高教程(3)-认识Set集合之LinkedHashSet
- Java集合:List、Set和Map的区别,ArrayList和LinkedList有何区别..........
- Java之集合框架 Set集合的特性以及LinkedHashSet的特性
- JAVA中的数据结构——集合类(线性表:Vector、Stack、LinkedList、set接口;键值对:Hashtable、Map接口<HashMap类、TreeMap类>)
- Java数据结构与算法之数据结构-逻辑结构-集合(七)------集合之Set接口和HashSet和TreeSet、LinkedHashSet实现类总结
- 集合框架 Vector LinkedList ArrayList HashSet LinkedHashSet TreeSet
- Set集合另一强悍的类LinkedHashSet
- 17. 集合类 (Set的子类HashSet、LinkedHashSet、TreeSet)
- java 集合 LinkedHashSet
- day17 集合框架 LinkedHashSet TreeSet Map 泛型
- 《Java源码解析》集合框架Set之LinkedHashSet