Thinking in java -- set和存储顺序

来源:互联网 发布:java lambda this 编辑:程序博客网 时间:2024/06/15 20:52

先运行一下代码,

package containers;//: containers/TypesForSets.java// Methods necessary to put your own type in a Set.import java.util.*;class SetType {    int i;    public SetType(int n) {        i = n;    }    public boolean equals(Object o) {        return o instanceof SetType && (i == ((SetType) o).i);    }    public String toString() {        return Integer.toString(i);    }}class HashType extends SetType {    public HashType(int n) {        super(n);    }    public int hashCode() {        return i;    }}class TreeType extends SetType implements Comparable<TreeType> {    public TreeType(int n) {        super(n);    }    public int compareTo(TreeType arg) {        return (arg.i < i ? -1 : (arg.i == i ? 0 : 1));    }}public class TypesForSets {    static <T> Set<T> fill(Set<T> set, Class<T> type) {        try {            for (int i = 0; i < 10; i++)                set.add(type.getConstructor(int.class).newInstance(i));        } catch (Exception e) {            throw new RuntimeException(e);        }        return set;    }    static <T> void test(Set<T> set, Class<T> type) {        fill(set, type);        fill(set, type); // Try to add duplicates        fill(set, type);        System.out.println(set);    }    public static void main(String[] args) {        test(new HashSet<HashType>(), HashType.class);        test(new LinkedHashSet<HashType>(), HashType.class);        test(new TreeSet<TreeType>(), TreeType.class);        // Things that don't work:        test(new HashSet<SetType>(), SetType.class);        test(new HashSet<TreeType>(), TreeType.class);        test(new LinkedHashSet<SetType>(), SetType.class);        test(new LinkedHashSet<TreeType>(), TreeType.class);        try {            test(new TreeSet<SetType>(), SetType.class);        } catch (Exception e) {            System.out.println(e.getMessage());        }        try {            test(new TreeSet<HashType>(), HashType.class);        } catch (Exception e) {            System.out.println(e.getMessage());        }    }} /*     * Output: (Sample) [2, 4, 9, 8, 6, 1, 3, 7, 5, 0] [0, 1, 2, 3, 4, 5, 6, 7,     * 8, 9] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] [9, 9, 7, 5, 1, 2, 6, 3, 0, 7, 2, 4,     * 4, 7, 9, 1, 3, 6, 2, 4, 3, 0, 5, 0, 8, 8, 8, 6, 5, 1] [0, 5, 5, 6, 5, 0,     * 3, 1, 9, 8, 4, 2, 3, 9, 7, 3, 4, 4, 0, 7, 1, 9, 6, 2, 1, 8, 2, 8, 6, 7]     * [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,     * 4, 5, 6, 7, 8, 9] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,     * 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] java.lang.ClassCastException: SetType     * cannot be cast to java.lang.Comparable java.lang.ClassCastException:     * HashType cannot be cast to java.lang.Comparable     */// :~

上面这段代码讲解了HashSet,LinkedHashSet,TreeSet的存储。
定义了四个类

  • SetType类重写了toString和equals方法。
  • HashType类继承SetType,定义hashCode方法。
  • TreeType类继承SetType,实现Comparable接口,实现compareTo方法
  • TypesForSets测试类,代码中通过fill方法,对不确定类型的Set方法塞值。

运行输出结果:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[1, 2, 9, 4, 0, 0, 5, 2, 3, 0, 6, 8, 5, 8, 8, 3, 3, 6, 4, 7, 9, 4, 1, 6, 2, 1, 5, 7, 9, 7]
[3, 7, 1, 8, 0, 8, 6, 3, 7, 3, 0, 8, 4, 5, 9, 2, 7, 5, 2, 4, 4, 9, 6, 9, 1, 2, 0, 1, 6, 5]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
java.lang.ClassCastException: containers.SetType cannot be cast to java.lang.Comparable
java.lang.ClassCastException: containers.HashType cannot be cast to java.lang.Comparable

分析结果:
第1、2test方法,是有序且不重复的存储。
第3个TreeType类实现compareTo方法,数据结构安装compareTo指定的规则进行排序
第4、5、6、7,都是没有去重的排序,理论上set容器应该是会去重的,原因是SetType与TreeType类均没有增加hashCode方法,详见这篇文章讲解重写hashcode的必要性:http://www.cnblogs.com/anrainie/archive/2012/04/27/2473196.html
第8、9,抛出了异常,

java.lang.ClassCastException: containers.SetType cannot be cast to java.lang.Comparable
java.lang.ClassCastException: containers.HashType cannot be cast to java.lang.Comparable

提示说没有找到java.lang.Comparable类,
引用Thinking in java内容

总结,

  1. *Set,存储的对象类,类必须重写hashCode方法。
  2. *TreeSet,存储的对象类,类必须实现Comparable接口的compareTo方法。

参考,“Thinking in java 17.6章节”

0 0
原创粉丝点击