LinkedHashSet的特征
LinkedHashSet是HashSet的一个子类,LinkedHashSet也根据HashCode的值来决定元素的存储位置,但同时它还用一个链表来维护元素的插入顺序,插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。查看LinkedHashSet的源码发现它是样的,
- //LinkedHashSet 源码
- public class LinkedHashSet extends HashSet
- implements Set, Cloneable, Serializable
- {
- public LinkedHashSet(int i, float f)
- {
- super(i, f, true);
- }
- ....
在JAVA7中, LinkedHashSet没有定义任何方法,只有四个构造函数,它的构造函数调用了父类(HashSet)的带三个参数的构造方法,父类的构造函数如下,
- //HashSet构造函数
- HashSet(int i, float f, boolean flag)
- {
- map = new LinkedHashMap(i, f);
- }
- ......
下面是一个LinkedHashSet维持元素插入顺序的例子,
- package colection.HashSet;
- import java.util.LinkedHashSet;
- public class LinkedHashSets {
- public static void main(String[] args) {
- LinkedHashSet lhs = new LinkedHashSet();
- lhs.add("abc");
- lhs.add("efg");
- lhs.add("hij");
- System.out.println(lhs);
- lhs.remove(new String("efg"));
- lhs.add("efg");
- System.out.println(lhs);
- }
- }
输入如下
- [abc, efg, hij]
- [abc, hij, efg]
TreeSet类的特征
TreeSet实现了SortedSet接口,顾名思义这是一种排序的Set集合,查看jdk源码发现底层是用TreeMap实现的,本质上是一个红黑树原理。 正因为它是排序了的,所以相对HashSet来说,TreeSet提供了一些额外的按排序位置访问元素的方法,例如first(), last(), lower(), higher(), subSet(), headSet(), tailSet().
TreeSet的排序分两种类型,一种是自然排序,另一种是定制排序。
自然排序(在元素中写排序规则)
TreeSet 会调用compareTo方法比较元素大小,然后按升序排序。所以自然排序中的元素对象,都必须实现了Comparable接口,否则会跑出异常。对于TreeSet判断元素是否重复的标准,也是调用元素从Comparable接口继承而来额compareTo方法,如果返回0则是重复元素(两个元素I相等)。Java的常见类都已经实现了Comparable接口,下面举例说明没有实现Comparable存入TreeSet时引发异常的情况。
- package collection.Set;
- import java.util.TreeSet;
- class Err {
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet();
- ts.add(new Err());
- ts.add(new Err());
- System.out.println(ts);
- }
- }
- Exception in thread "main" java.lang.ClassCastException: collection.Set.Err cannot be cast to java.lang.Comparable
- at java.util.TreeMap.compare(Unknown Source)
- at java.util.TreeMap.put(Unknown Source)
- at java.util.TreeSet.add(Unknown Source)
- at collection.Set.TreeSets.main(TreeSets.java:13)
- class Err implements Comparable {
- @Override
- public int compareTo(Object o) {
- // TODO Auto-generated method stub
- return 0;
- }
- }
还有个重要问题是,因为TreeSet会调用元素的compareTo方法,这就要求所有元素的类型都相同,否则也会发生异常。 也就是说,TreeSet只允许存入同一类的元素 。例如下面这个例子就会抛出类型转换异常
- package collection.Set;
- import java.util.TreeSet;
- class Err implements Comparable {
- @Override
- public int compareTo(Object o) {
- // TODO Auto-generated method stub
- return 0;
- }
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet();
- ts.add(1);
- ts.add("2");
- System.out.println(ts);
- }
- }
- Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
- at java.lang.String.compareTo(Unknown Source)
- at java.util.TreeMap.put(Unknown Source)
- at java.util.TreeSet.add(Unknown Source)
- at collection.Set.TreeSets.main(TreeSets.java:18)
定制排序(在集合中写排序规则)
TreeSet还有一种排序就是定制排序,定制排序时候,需要关联一个 Comparator对象,由Comparator提供排序逻辑。下面就是一个使用Lambda表达式代替Comparator对象来提供定制排序的例子。 下面是一个定制排序的列子
- package collection.Set;
- import java.util.Comparator;
- import java.util.TreeSet;
- class M {
- int age;
- public M(int age) {
- this.age = age;
- }
- public String toString() {
- return "M[age:" + age + "]";
- }
- }
- class MyCommpare implements Comparator{
- public int compare(Object o1, Object o2){
- M m1 = (M)o1;
- M m2 = (M)o2;
- return m1.age > m2.age ? 1 : m1.age < m2.age ? -1 : 0;
- }
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet(new MyCommpare());
- ts.add(new M(5));
- ts.add(new M(3));
- ts.add(new M(9));
- System.out.println(ts);
- }
- }
当然将Comparator直接写入TreeSet初始化中也可以。如下。
- package collection.Set;
- import java.util.Comparator;
- import java.util.TreeSet;
- class M {
- int age;
- public M(int age) {
- this.age = age;
- }
- public String toString() {
- return "M[age:" + age + "]";
- }
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet(new Comparator() {
- public int compare(Object o1, Object o2) {
- M m1 = (M)o1;
- M m2 = (M)o2;
- return m1.age > m2.age ? -1 : m1.age < m2.age ? 1 : 0;
- }
- });
- ts.add(new M(5));
- ts.add(new M(3));
- ts.add(new M(9));
- System.out.println(ts);
- }
- }
EnumSet特征
EnumSet顾名思义就是专为枚举类型设计的集合,因此集合元素必须是枚举类型,否则会抛出异常。 EnumSet集合也是有序的,其顺序就是Enum类内元素定义的顺序。EnumSet存取的速度非常快,批量操作的速度也很快。EnumSet主要提供以下方法,allOf, complementOf, copyOf, noneOf, of, range等。注意到EnumSet并没有提供任何构造函数,要创建一个EnumSet集合对象,只需要调用allOf等方法,下面是一个EnumSet的例子。
- package collection.Set;
- import java.util.EnumSet;
- enum Season
- {
- SPRING, SUMMER, FALL, WINTER
- }
- public class EnumSets {
- public static void main(String[] args) {
- //必须用元素对象的类类型来初始化,即Season.class
- EnumSet es1 = EnumSet.allOf(Season.class);
- System.out.println(es1);
- EnumSet es2 = EnumSet.noneOf(Season.class);
- es2.add(Season.WINTER);
- es2.add(Season.SUMMER);
- System.out.println(es2);
- EnumSet es3 = EnumSet.of(Season.WINTER, Season.SUMMER);
- System.out.println(es3);
- EnumSet es4 = EnumSet.range(Season.SUMMER, Season.WINTER);
- System.out.println(es4);
- EnumSet es5 = EnumSet.complementOf(es4);
- System.out.println(es5);
- }
- }
- [SPRING, SUMMER, FALL, WINTER]
- [SUMMER, WINTER]
- [SUMMER, WINTER]
- [SUMMER, FALL, WINTER]
- [SPRING]
各种集合性能分析
- HashSet和TreeSet是Set集合中用得最多的I集合。HashSet总是比TreeSet集合性能好,因为HashSet不需要额维护元素的顺序。
- LinkedHashSet需要用额外的链表维护元素的插入顺序,因此在插入时性能比HashSet低,但在迭代访问(遍历)时性能更高。因为插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。
- EnumSet元素是所有Set元素中性能最好的,但是它只能保存Enum类型的元素
LinkedHashSet的特征
LinkedHashSet是HashSet的一个子类,LinkedHashSet也根据HashCode的值来决定元素的存储位置,但同时它还用一个链表来维护元素的插入顺序,插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。查看LinkedHashSet的源码发现它是样的,
- //LinkedHashSet 源码
- public class LinkedHashSet extends HashSet
- implements Set, Cloneable, Serializable
- {
- public LinkedHashSet(int i, float f)
- {
- super(i, f, true);
- }
- ....
在JAVA7中, LinkedHashSet没有定义任何方法,只有四个构造函数,它的构造函数调用了父类(HashSet)的带三个参数的构造方法,父类的构造函数如下,
- //HashSet构造函数
- HashSet(int i, float f, boolean flag)
- {
- map = new LinkedHashMap(i, f);
- }
- ......
下面是一个LinkedHashSet维持元素插入顺序的例子,
- package colection.HashSet;
- import java.util.LinkedHashSet;
- public class LinkedHashSets {
- public static void main(String[] args) {
- LinkedHashSet lhs = new LinkedHashSet();
- lhs.add("abc");
- lhs.add("efg");
- lhs.add("hij");
- System.out.println(lhs);
- lhs.remove(new String("efg"));
- lhs.add("efg");
- System.out.println(lhs);
- }
- }
输入如下
- [abc, efg, hij]
- [abc, hij, efg]
TreeSet类的特征
TreeSet实现了SortedSet接口,顾名思义这是一种排序的Set集合,查看jdk源码发现底层是用TreeMap实现的,本质上是一个红黑树原理。 正因为它是排序了的,所以相对HashSet来说,TreeSet提供了一些额外的按排序位置访问元素的方法,例如first(), last(), lower(), higher(), subSet(), headSet(), tailSet().
TreeSet的排序分两种类型,一种是自然排序,另一种是定制排序。
自然排序(在元素中写排序规则)
TreeSet 会调用compareTo方法比较元素大小,然后按升序排序。所以自然排序中的元素对象,都必须实现了Comparable接口,否则会跑出异常。对于TreeSet判断元素是否重复的标准,也是调用元素从Comparable接口继承而来额compareTo方法,如果返回0则是重复元素(两个元素I相等)。Java的常见类都已经实现了Comparable接口,下面举例说明没有实现Comparable存入TreeSet时引发异常的情况。
- package collection.Set;
- import java.util.TreeSet;
- class Err {
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet();
- ts.add(new Err());
- ts.add(new Err());
- System.out.println(ts);
- }
- }
- Exception in thread "main" java.lang.ClassCastException: collection.Set.Err cannot be cast to java.lang.Comparable
- at java.util.TreeMap.compare(Unknown Source)
- at java.util.TreeMap.put(Unknown Source)
- at java.util.TreeSet.add(Unknown Source)
- at collection.Set.TreeSets.main(TreeSets.java:13)
- class Err implements Comparable {
- @Override
- public int compareTo(Object o) {
- // TODO Auto-generated method stub
- return 0;
- }
- }
还有个重要问题是,因为TreeSet会调用元素的compareTo方法,这就要求所有元素的类型都相同,否则也会发生异常。 也就是说,TreeSet只允许存入同一类的元素 。例如下面这个例子就会抛出类型转换异常
- package collection.Set;
- import java.util.TreeSet;
- class Err implements Comparable {
- @Override
- public int compareTo(Object o) {
- // TODO Auto-generated method stub
- return 0;
- }
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet();
- ts.add(1);
- ts.add("2");
- System.out.println(ts);
- }
- }
- Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
- at java.lang.String.compareTo(Unknown Source)
- at java.util.TreeMap.put(Unknown Source)
- at java.util.TreeSet.add(Unknown Source)
- at collection.Set.TreeSets.main(TreeSets.java:18)
定制排序(在集合中写排序规则)
TreeSet还有一种排序就是定制排序,定制排序时候,需要关联一个 Comparator对象,由Comparator提供排序逻辑。下面就是一个使用Lambda表达式代替Comparator对象来提供定制排序的例子。 下面是一个定制排序的列子
- package collection.Set;
- import java.util.Comparator;
- import java.util.TreeSet;
- class M {
- int age;
- public M(int age) {
- this.age = age;
- }
- public String toString() {
- return "M[age:" + age + "]";
- }
- }
- class MyCommpare implements Comparator{
- public int compare(Object o1, Object o2){
- M m1 = (M)o1;
- M m2 = (M)o2;
- return m1.age > m2.age ? 1 : m1.age < m2.age ? -1 : 0;
- }
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet(new MyCommpare());
- ts.add(new M(5));
- ts.add(new M(3));
- ts.add(new M(9));
- System.out.println(ts);
- }
- }
当然将Comparator直接写入TreeSet初始化中也可以。如下。
- package collection.Set;
- import java.util.Comparator;
- import java.util.TreeSet;
- class M {
- int age;
- public M(int age) {
- this.age = age;
- }
- public String toString() {
- return "M[age:" + age + "]";
- }
- }
- public class TreeSets {
- public static void main(String[] args) {
- TreeSet ts = new TreeSet(new Comparator() {
- public int compare(Object o1, Object o2) {
- M m1 = (M)o1;
- M m2 = (M)o2;
- return m1.age > m2.age ? -1 : m1.age < m2.age ? 1 : 0;
- }
- });
- ts.add(new M(5));
- ts.add(new M(3));
- ts.add(new M(9));
- System.out.println(ts);
- }
- }
EnumSet特征
EnumSet顾名思义就是专为枚举类型设计的集合,因此集合元素必须是枚举类型,否则会抛出异常。 EnumSet集合也是有序的,其顺序就是Enum类内元素定义的顺序。EnumSet存取的速度非常快,批量操作的速度也很快。EnumSet主要提供以下方法,allOf, complementOf, copyOf, noneOf, of, range等。注意到EnumSet并没有提供任何构造函数,要创建一个EnumSet集合对象,只需要调用allOf等方法,下面是一个EnumSet的例子。
- package collection.Set;
- import java.util.EnumSet;
- enum Season
- {
- SPRING, SUMMER, FALL, WINTER
- }
- public class EnumSets {
- public static void main(String[] args) {
- //必须用元素对象的类类型来初始化,即Season.class
- EnumSet es1 = EnumSet.allOf(Season.class);
- System.out.println(es1);
- EnumSet es2 = EnumSet.noneOf(Season.class);
- es2.add(Season.WINTER);
- es2.add(Season.SUMMER);
- System.out.println(es2);
- EnumSet es3 = EnumSet.of(Season.WINTER, Season.SUMMER);
- System.out.println(es3);
- EnumSet es4 = EnumSet.range(Season.SUMMER, Season.WINTER);
- System.out.println(es4);
- EnumSet es5 = EnumSet.complementOf(es4);
- System.out.println(es5);
- }
- }
- [SPRING, SUMMER, FALL, WINTER]
- [SUMMER, WINTER]
- [SUMMER, WINTER]
- [SUMMER, FALL, WINTER]
- [SPRING]
各种集合性能分析
- HashSet和TreeSet是Set集合中用得最多的I集合。HashSet总是比TreeSet集合性能好,因为HashSet不需要额维护元素的顺序。
- LinkedHashSet需要用额外的链表维护元素的插入顺序,因此在插入时性能比HashSet低,但在迭代访问(遍历)时性能更高。因为插入的时候即要计算hashCode又要维护链表,而遍历的时候只需要按链表来访问元素。
- EnumSet元素是所有Set元素中性能最好的,但是它只能保存Enum类型的元素