zoukankan      html  css  js  c++  java
  • 排序及重复元素去重的说明,TreeSet,HashSet

    先看下面一段代码:

    package 类集;
    import java.util.Set;
    import java.util.TreeSet;
    class Person{
        private String name ;
        private int age ;
        public Person(String name,int age){
            this.name = name ;
            this.age = age ;
        }
        public String gtoString(){
            return "姓名:" + this.name + ";年龄:" + this.age ;
        }
    };
    
    public class test1{
        public static void main(String args[]){
            Set<Person> allSet = new TreeSet<Person>() ;
            allSet.add(new Person("张三",30)) ;
            allSet.add(new Person("李四",31)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("赵六",33)) ;
            allSet.add(new Person("孙七",33)) ;
            System.out.println(allSet) ;
        }
    };

    运行结果:

    Exception in thread "main" java.lang.ClassCastException: 类集.Person cannot be cast to java.lang.Comparable
        at java.util.TreeMap.compare(TreeMap.java:1294)
        at java.util.TreeMap.put(TreeMap.java:538)
        at java.util.TreeSet.add(TreeSet.java:255)
        at 类集.test1.main(test1.java:19)

    报错。此时没有排序,因为java.lang.comparable类导致。

    comparable是进行排序的接口。一个对象数组要想排序需要依靠comparable接口完成。对于treeset一样,要想进行排序,则对象所在的类也要依靠comparable接口

    修改如下,要想排序,对象所在的类也要依靠comparable接口(继承之)

    package 类集;
    import java.util.Set;
    import java.util.TreeSet;
    class Person implements Comparable<Person>{
        private String name ;
        private int age ;
        public Person(String name,int age){
            this.name = name ;
            this.age = age ;
        }
        public String toString(){
            return "姓名:" + this.name + ";年龄:" + this.age ;
        }
        public int compareTo(Person per){  //这里需要复习comparable接口的知识
            if(this.age>per.age){
                return 1 ;
            }else if(this.age<per.age){
                return -1 ;
            }else{
                return 0 ;
            }
        }
    };
    public class test1{
        public static void main(String args[]){
            Set<Person> allSet = new TreeSet<Person>() ;
            allSet.add(new Person("张三",30)) ;
            allSet.add(new Person("李四",31)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("赵六",33)) ;
            allSet.add(new Person("孙七",33)) ;
            System.out.println(allSet) ;
        }
    };

    输出结果:

    [姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32, 姓名:赵六;年龄:33]

    string类既然可以使用TreeSet排序,则String中肯定已经实现了Comparable接口。

    string类定义如下:

    public final class Stringextends Objectimplements Serializable, Comparable<String>, CharSequence

    此时是可以排序了,但是结果有问题,

    [姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32, 姓名:赵六;年龄:33]

    发现去掉了重复的元素(王五),依靠的是comparable接口完成的。孙七没有加入进来,因为孙七和赵6年龄是完全一样的,而此时的comparable接口比较的只是年龄。

    为了保证正确,所有的属性都应该进行比较:改成如下:

    package 类集;
    import java.util.Set;
    import java.util.TreeSet;
    class Person implements Comparable<Person>{
        private String name ;
        private int age ;
        public Person(String name,int age){
            this.name = name ;
            this.age = age ;
        }
        public String toString(){
            return "姓名:" + this.name + ";年龄:" + this.age ;
        }
        public int compareTo(Person per){
            if(this.age>per.age){
                return 1 ;
            }else if(this.age<per.age){
                return -1 ;
            }else{
                return this.name.compareTo(per.name) ;    // 调用String中的compareTo()方法
            }
        }
    };
    public class test1{
        public static void main(String args[]){
            Set<Person> allSet = new TreeSet<Person>() ;
            allSet.add(new Person("张三",30)) ;
            allSet.add(new Person("李四",31)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("赵六",33)) ;
            allSet.add(new Person("孙七",33)) ;
            System.out.println(allSet) ;
        }
    };

    输出结果:

    [姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32, 姓名:孙七;年龄:33, 姓名:赵六;年龄:33]

    此时的去重元素并不是真正意义上的重复元素取消

    用hashSet试试,hashset不排序。

    package 类集;
    import java.util.HashSet;
    import java.util.Set;
    class Person{
        private String name ;
        private int age ;
        public Person(String name,int age){
            this.name = name ;
            this.age = age ;
        }
        public String toString(){
            return "姓名:" + this.name + ";年龄:" + this.age ;
        }
    };
    public class test1{
        public static void main(String args[]){
            Set<Person> allSet = new HashSet<Person>() ;
            allSet.add(new Person("张三",30)) ;
            allSet.add(new Person("李四",31)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("赵六",33)) ;
            allSet.add(new Person("孙七",33)) ;    
            System.out.println(allSet) ;
        }
    };

    输出结果:

    [姓名:王五;年龄:32, 姓名:赵六;年龄:33, 姓名:孙七;年龄:33, 姓名:王五;年龄:32, 姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:王五;年龄:32]

    此时并没有去掉重复的元素,该如何取消呢,  

    如果要想去掉重复,则需要object类中两个方法帮助。

    1,hashcode():表示一个唯一编码,一般通过计算表示。   

    2)equals():进行对象的比较操作。

    我们需要覆写这两个方法

    package 类集;
    import java.util.HashSet;
    import java.util.Set;
    class Person{
        private String name ;
        private int age ;
        public Person(String name,int age){
            this.name = name ;
            this.age = age ;
        }
        public boolean equals(Object obj){    // 覆写equals,完成对象比较
            if(this==obj){
                return true ;
            }
            if(!(obj instanceof Person)){
                return false ;
            }
            Person p = (Person)obj ;    // 向下转型
            if(this.name.equals(p.name)&&this.age==p.age){
                return true ;
            }else{
                return false ;
            }
        }
        public int hashCode(){
            return this.name.hashCode() * this.age    ; // 自己定义一个公式,如上所写。
        }
        public String toString(){
            return "姓名:" + this.name + ";年龄:" + this.age ;
        }
    };
    public class test1{
        public static void main(String args[]){
            Set<Person> allSet = new HashSet<Person>() ;
            allSet.add(new Person("张三",30)) ;
            allSet.add(new Person("李四",31)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("王五",32)) ;
            allSet.add(new Person("赵六",33)) ;
            allSet.add(new Person("孙七",33)) ;    
            System.out.println(allSet) ;
        }
    };

    输出结果:

    [姓名:赵六;年龄:33, 姓名:王五;年龄:32, 姓名:张三;年龄:30, 姓名:李四;年龄:31, 姓名:孙七;年龄:33]

    此时没有了重复元素

    如果要想使用Set,必须注意以上两个问题,

    1,一个好的类应该覆写object类中的equals(),hashCode(),toString()三个方法,实际上在String()中已经覆写完成了。

    2,Set接口依靠hashCode()和equals()完成重复元素的判断,关于这一点,在以后的Map接口中也有体现。

    3,TreeSet依靠Comparable完成排序的操作

  • 相关阅读:
    HDU4565
    CF861D
    UVA 11651
    HDU5950
    POJ3267
    POJ1094
    POJ1905
    HDU3567
    进程的同步与互斥
    预防死锁,检测死锁,避免死锁,解除死锁....
  • 原文地址:https://www.cnblogs.com/alsf/p/6224073.html
Copyright © 2011-2022 走看看