• TreeSet和TreeMap的输出


    如果加入TreeSet和TreeMap的元素没有实现comprable中的compareTo()方法,那么会报错“treeset cannot be cast to java.lang.Comparable”.

    要解决这个问题有两种方法:

    (1)让元素自身具有比较性;可以实现Comparable接口,实现compareTo()方法;

    (2)让集合自身具有比较性;可以定义比较器,即让集合实现Comparator接口,然后实现compare()方法;

    方法一:

    因此需要对元素类型实现Comparable借口,并实现compareTo()方法,即告诉TreeSet和TreeMap你要怎么排列,它才能进行排序。

    基础类:

    package niukewang;
    
    import java.util.Objects;
    
    public class setClass implements Comparable<setClass>{
    
        String a;
        String b;
        public setClass(String a, String b)
        {
            this.a=a;
            this.b=b;    
        }
        
        public int hashCode() {
            return a.hashCode();
        }
        
        public boolean equals(Object obj)
        {
            if(obj==null) return false;
            
            if(getClass() != obj.getClass()) return false;
            
            final setClass s=(setClass)obj;
            
            return Objects.equals(this.a, s.a);
        }
    
        @Override
        public int compareTo(setClass o) {
            int num=this.b.compareTo(o.b);
            return num;
        }
    }

    测试类:

    package niukewang;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Hashtable;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.TreeMap;
    import java.util.TreeSet;
    import java.util.Vector;
    
    
    public class test1 {
    
        public static void main(String args[]) 
        { 
            setClass s1=new setClass("http://www.yjbys.com/", "same0");
            setClass s2=new setClass("http://www.yjbys.com1/", "same0");
            setClass s3=new setClass("http://www.yjbys.com2/", "same2");
            setClass s4=new setClass("http://www.yjbys.com2/", "same3");
            
            //hasSet
            System.out.println("hasSet......");
            Set<setClass> set=new HashSet<setClass>();
            set.add(s1);
            set.add(s2);
            set.add(s3);
            set.add(s4);
            Iterator it= set.iterator();
            while(it.hasNext())
            {
                setClass ob=(setClass)it.next();
                System.out.println(ob.a);
            }
            
            //TreeSet
            System.out.println("
    TreeSet........");
            Set<setClass> tree=new TreeSet<setClass>();
            tree.add(s1);
            tree.add(s2);
            tree.add(s3);
            tree.add(s4);
            Iterator treeit=tree.iterator();
            while(treeit.hasNext())
            {
                setClass ob=(setClass) treeit.next();
                System.out.println(ob.a);
            }
            
            //TreeMap
            System.out.println("
    TreeMap.........");
            Map<setClass,String> treemap=new TreeMap<setClass,String>();
            treemap.put(s1, "TreeMap one");
            treemap.put(s2, "TreeMap two");
            treemap.put(s3, "TreeMap three");
            treemap.put(s4, "TreeMap four");
            for(Map.Entry<setClass, String> entry: treemap.entrySet())
            {
                System.out.println("The treemap key is "+entry.getKey().a+" The value is "+ entry.getValue());
            }
            
            //HasMap
            System.out.println("
    HashMap......");
            Map<setClass,String> hashmap=new HashMap<setClass, String>();
            hashmap.put(s1, "HashMap one");
            hashmap.put(s2, "HashMap two");
            hashmap.put(s3, "HashMap three");
            hashmap.put(s4, "HashMap four");
            for(Map.Entry<setClass, String> entry : hashmap.entrySet())
            {
                System.out.println("The key is "+entry.getKey().a+" The value is "+entry.getValue());
            }
            
            //HasTable
            System.out.println("
    HashTable......");
            Map<setClass,String> hashtable=new Hashtable<setClass, String>();
            hashtable.put(s1, "HashTable one");
            hashtable.put(s2, "HashTable two");
            hashtable.put(s3, "HashTable three");
            hashtable.put(s4, "HashTable four");
            for(Map.Entry<setClass, String> entry: hashtable.entrySet())
            {
                System.out.println("The HashTable key is "+entry.getKey().a+" The HashTable value is "+entry.getValue());
            }
            
            //LinkedList
            System.out.println("
    LinkedList.....");
            List list=new LinkedList();
            list.add(s1);
            list.add(s2);
            list.add(s3);
            list.add(s4);
            Iterator listit=list.iterator();
            while(listit.hasNext())
            {
                setClass ob=(setClass)listit.next();
                System.out.println(ob.a);
            }
    
            //ArrayList
            System.out.println("
    ArrayList.....");
            List array=new ArrayList();
            array.add(s1);
            array.add(s2);
            array.add(s3);
            array.add(s4);
            Iterator arrayit=array.iterator();
            while(arrayit.hasNext())
            {
                setClass ob=(setClass)arrayit.next();
                System.out.println(ob.a);
            }
            
            //vector
            System.out.println("
    vector.....");
            Vector v=new Vector();
            v.add(s1);
            v.add(s2);
            v.add(s3);
            v.add(s4);
            Iterator vit=v.iterator();
            while(vit.hasNext())
            {
                setClass  ob=(setClass)vit.next();
                System.out.println(ob.a);
            }
                
        }
    }

    输出结果:

    hasSet......
    http://www.yjbys.com1/
    http://www.yjbys.com/
    http://www.yjbys.com2/
    
    TreeSet........
    http://www.yjbys.com/
    http://www.yjbys.com2/
    http://www.yjbys.com2/
    
    TreeMap.........
    The treemap key is http://www.yjbys.com/ The value is TreeMap two
    The treemap key is http://www.yjbys.com2/ The value is TreeMap three
    The treemap key is http://www.yjbys.com2/ The value is TreeMap four
    
    HashMap......
    The key is http://www.yjbys.com1/ The value is HashMap two
    The key is http://www.yjbys.com/ The value is HashMap one
    The key is http://www.yjbys.com2/ The value is HashMap four
    
    HashTable......
    The HashTable key is http://www.yjbys.com1/ The HashTable value is HashTable two
    The HashTable key is http://www.yjbys.com/ The HashTable value is HashTable one
    The HashTable key is http://www.yjbys.com2/ The HashTable value is HashTable four
    
    LinkedList.....
    http://www.yjbys.com/
    http://www.yjbys.com1/
    http://www.yjbys.com2/
    http://www.yjbys.com2/
    
    ArrayList.....
    http://www.yjbys.com/
    http://www.yjbys.com1/
    http://www.yjbys.com2/
    http://www.yjbys.com2/
    
    vector.....
    http://www.yjbys.com/
    http://www.yjbys.com1/
    http://www.yjbys.com2/
    http://www.yjbys.com2/

    TreeSet并不像hashSet那样,用hashCode和equals取决于元素是否相等。
    而是取决于compareTo()方法中指定的排序的方式;

      setClass s1=new setClass("http://www.yjbys.com/", "same0");
      setClass s2=new setClass("http://www.yjbys.com1/", "same0");
      setClass s3=new setClass("http://www.yjbys.com2/", "same2");
      setClass s4=new setClass("http://www.yjbys.com2/", "same3");

    如果用hashCode和equals取决于元素是否相等,那么s3和s4是相等的;

    而此时候,是根据compareTo()方法中的第二个字符串b来判断是否相等,则s1与s2相等,s3和s4不相等,所以才有这样的输出:

    TreeSet........
    http://www.yjbys.com/
    http://www.yjbys.com2/
    http://www.yjbys.com2/

    方法二:

    定义比较器,让集合实现Comparator接口,然后实现compare方法,则集合自身具有比较性。

    其中Class Student 是实现了Comparable接口的,是元素本身具有比较性,在main方法中添加到TreeSet中的时候,能体现出来,通过年龄来比较大小;如果年龄和姓名相同,则是完全相等;

    其中成员方法testComparator()中,定义了一个TreeSet,使其实现Comparator接口,并实现了方法compare(),通过setClass类中的a的属性的大小;因此此方法中的TreeSet具有比较性;

    package niukewang;
    
    import java.util.Comparator;
    import java.util.Set;
    import java.util.TreeSet;
    
    import org.junit.Test;
    
    //非线程安全
    public class TreeSetTest {
        /**
         * TreeSet:它可以给Set集合中的元素进行指定方式的排序。 保证元素唯一性的方式:通过比较的结果是否为0. 底层数据结构是:二叉树。
         * 
         * 排序的第一种方式: 让元素自身具备比较性。只要让元素实现Comparable接口,覆盖compareTo方法即可。
         * 
         * 但是,如果元素自身不具备比较性,或者元素自身具备的比较性,不是所需要的。
         * 比如,学生的自然排序是按年龄排序,现在想要按照学生姓名排序。还可以不改动原有代码。 这时怎么办呢?
         * 
         * 排序的第二种方式:自定比较器的方式。这时可以让集合自身具备比较性。
         * 
         * 可以定义一个类实现Comparator接口,覆盖compare方法。
         * 将该Comparator接口子类对象作为实际参数传递给TreeSet集合构造函数。
         */
        public static void main(String[] args) {
            TreeSet<Student> ts = new TreeSet<Student>();
            // Student如果不实现Comparable,add时会出错,Student cannot be cast to java.lang.Comparable
            //添加第一个对象时,TreeSet里没有任何元素,所以没有问题;
            //当添加第二个Err对象时,TreeSet就会调用该对象的compareTo(Object obj)方法与集合中其他元素进行比较——
            //如果对应的类没有实现Comparable接口,则会引发ClassCastException异常
            // add方法内部会对插入的数据进行排序,此时元素自身具备比较性,因为其实现了Comparable接口
            ts.add(new Student("lisi0", 30));
            ts.add(new Student("lisixx", 29));
            ts.add(new Student("lisi9", 29));
            ts.add(new Student("lisi8", 38));
            // 重复插入无效,但是不报错(根据年龄和名字进行比较,都相同,视为同一个学生)
            ts.add(new Student("lisixx", 29));
            ts.add(new Student("lisixx", 28));
            ts.add(new Student("lisi4", 14));
            ts.add(new Student("lisi7", 27));
            System.out.println(ts);
            
            System.out.println("testComparator........
    ");
            TreeSetTest ob=new TreeSetTest();
            ob.testComprator();
        }
        
        //自定义比较器,让集合自身具备比较性
        @Test
        public void testComprator()
        {
            setClass s1=new setClass("http://www.yjbys.com/", "same0");
            setClass s2=new setClass("http://www.yjbys.com1/", "same0");
            setClass s3=new setClass("http://www.yjbys.com2/", "same2");
            setClass s4=new setClass("http://www.yjbys.com2/", "same3");
            
            Set<setClass> treeset=new TreeSet<setClass>(new Comparator<setClass>(){
    
                @Override
                public int compare(setClass arg0, setClass arg1) {
                    // TODO Auto-generated method stub
                    int num=arg0.a.compareTo(arg1.a); //只比较属性a的大小
                    return num;
                }
            });
            
            treeset.add(s1);
            treeset.add(s2);
            treeset.add(s3);
            treeset.add(s4);
    
            System.out.println(treeset);
        }
    
        //同姓名同年龄的学生视为同一个学生
        public static class Student implements Comparable<Student> {
    
            private int age;
            private String name;
    
            public Student(String name, int age) {
                this.age = age;
                this.name = name;
            }
    
            @Override
            public int compareTo(Student stu) {
                int num = new Integer(this.age).compareTo(new Integer(stu.age));
                return num == 0 ? this.name.compareTo(stu.name) : num;
            }
    
            public String toString() {
                return name + "::" + age;
            }
    
            public int getAge() {
                return age;
            }
    
            public void setAge(int age) {
                this.age = age;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
        }
    }

    运行结果:

    [lisi4::14, lisi7::27, lisixx::28, lisi9::29, lisixx::29, lisi0::30, lisi8::38]
    testComparator........
    
    [http://www.yjbys.com/ :: same0, http://www.yjbys.com1/ :: same0, http://www.yjbys.com2/ :: same2]

    由上图可知:
    Stuent类是通过年龄判断的,所以按年龄排序;只有姓名和年龄都相同时,则认为是相同的,所以ts.add(new Student("lisixx", 29))不会重复添加;其他因为姓名不同,就算年龄相同,也认为是不相同的;

    setClass类,是根据setClass中的属性a的值是否相等,就算hashCode和equals方法被重写了,它只看比较性。

    注意:

    如果在setClass类中,如果没有重写public String toString()方法,则会输出类似下面的输出:

    [niukewang.setClass@cbf33da, niukewang.setClass@8b2747d3, niukewang.setClass@8b2747f2]

    但是如果重写了public String toString()方法:

     public String toString()
     {
      return this.a+" :: "+this.b;
     }

    则会输出:[http://www.yjbys.com/ :: same0, http://www.yjbys.com1/ :: same0, http://www.yjbys.com2/ :: same2]

  • 相关阅读:
    循环顺序队列
    iscsi与multipath
    MySQL 数据库设计 笔记与总结(4)维护优化
    [Swift]LeetCode6. Z字形变换 | ZigZag Conversion
    [Swift]八大排序算法(八):基数排序
    [Swift]八大排序算法(七):归并排序
    [Swift]八大排序算法(六):希尔排序
    [Swift]八大排序算法(五):插入排序
    [Swift]八大排序算法(四):堆排序
    [Swift]八大排序算法(三):选择排序 和 简单选择排序
  • 原文地址:https://www.cnblogs.com/Berryxiong/p/6139452.html
Copyright © 2020-2023  润新知