zoukankan      html  css  js  c++  java
  • Java类集Set接口

    Set接口的定义

    Set接口也是Collection接口的子接口,但是与Collection或List接口不同的是,Set接口中不能加入重复的元素,其定义如下:

    public interface Set<E> extends Colletion<E>

    从定义上可以发现,Set接口与List接口的定义并没有太大的区别,但是Set接口的主要方法与Collection是一致的,也就是说Set接口并没有对Collection进行扩充。

    Set接口的常用子类

    1.散列的存放:HashSet

    验证HashSet类
    1 package com.yuchao.collection;
    2
    3  import java.util.HashSet;
    4  import java.util.Set;
    5
    6 public class HashSetDemo {
    7
    8 /**
    9 * @param args
    10 */
    11 public static void main(String[] args) {
    12 // TODO Auto-generated method stub
    13 Set<String> allSet=new HashSet<String>();
    14 allSet.add("A");
    15 allSet.add("B");
    16 allSet.add("C");
    17 allSet.add("C");
    18 allSet.add("D");
    19 allSet.add("D");
    20 allSet.add("D");
    21 allSet.add("E");
    22 System.out.println(allSet);
    23 }
    24
    25 }

    程序运行结果:

    [D,A,C,B,E]

    从程序的运行结果可以清楚地看出,对于重复元素只会增加一次,而且程序运行时向集合中加入元素的顺序并不是集合中的保存顺序,证明HashSet类中的元素是无序排列的。

    2.有序的存放:TreeSet

    验证TreeSet类
    1 package com.yuchao.collection;
    2
    3 import java.util.HashSet;
    4 import java.util.Set;
    5
    6 public class HashSetDemo {
    7
    8 /**
    9 * @param args
    10 */
    11 public static void main(String[] args) {
    12 // TODO Auto-generated method stub
    13 Set<String> allSet=new HashSet<String>();
    14 allSet.add("A");
    15 allSet.add("B");
    16 allSet.add("C");
    17 allSet.add("C");
    18 allSet.add("D");
    19 allSet.add("D");
    20 allSet.add("D");
    21 allSet.add("E");
    22 System.out.println(allSet);
    23 }
    24
    25 }

    程序运行结果:

    [A,B,C,D,E]

    程序在向集合中插入数据时是没有顺序的,但是输出之类数据是有序的,所以TreeSet是可以排序的。

    3.关于TreeSet的一些思考

    既然TreeSet本身是可以排序的,那么自定义的一个类,是否也可以随意进行排序呢?

    自定义类排序
    1 package com.yuchao.collection;
    2
    3 import java.util.Set;
    4 import java.util.TreeSet;
    5
    6 public class TreeSetDemo {
    7
    8 /**
    9 * @param args
    10 */
    11 public static void main(String[] args) {
    12 // TODO Auto-generated method stub
    13 Set<Person> allSet=new TreeSet<Person>();
    14 allSet.add(new Person("张三", 30));
    15 allSet.add(new Person("李四", 31));
    16 allSet.add(new Person("王五", 32));
    17 allSet.add(new Person("王五", 32));
    18 allSet.add(new Person("王五", 32));
    19 allSet.add(new Person("赵六", 33));
    20 allSet.add(new Person("孙七", 33));
    21 System.out.println(allSet);
    22
    23 }
    24
    25 }
    26
    27 class Person
    28 {
    29 private String name;
    30 private int age;
    31 public Person(String name,int age)
    32 {
    33 this.name=name;
    34 this.age=age;
    35 }
    36
    37 public String toString()
    38 {
    39 return "姓名:"+this.name+";"+"年龄:"+this.age;
    40 }
    41 }

    程序运行时出现以下错误:

    Exception in thread "main" java.lang.ClassCastException: com.yuchao.collection.Person cannot be cast to java.lang.Comparable
        at java.util.TreeMap.put(TreeMap.java:542)
        at java.util.TreeSet.add(TreeSet.java:238)
        at com.yuchao.collection.TreeSetDemo.main(TreeSetDemo.java:15)

    以下程序代码出现了类转换异常,会出现这样的问题,是因为TreeSet中的元素是有序存放,所以对一个对象必须指定好其排序规则,且TreeSet中每个对象所在的类都必须实现Comparable接口才可以正常使用。

    指定排序规则的自定义类排序
    1 package com.yuchao.collection;
    2
    3 import java.util.Set;
    4 import java.util.TreeSet;
    5
    6 public class TreeSetDemo {
    7
    8 /**
    9 * @param args
    10 */
    11 public static void main(String[] args) {
    12 // TODO Auto-generated method stub
    13 Set<Person> allSet=new TreeSet<Person>();
    14 allSet.add(new Person("张三", 30));
    15 allSet.add(new Person("李四", 31));
    16 allSet.add(new Person("王五", 32));
    17 allSet.add(new Person("王五", 32));
    18 allSet.add(new Person("王五", 32));
    19 allSet.add(new Person("赵六", 33));
    20 allSet.add(new Person("孙七", 33));
    21 System.out.println(allSet);
    22 }
    23
    24 }
    25
    26 class Person implements Comparable<Person>
    27 {
    28 private String name;
    29 private int age;
    30 public Person(String name,int age)
    31 {
    32 this.name=name;
    33 this.age=age;
    34 }
    35
    36 public String toString()
    37 {
    38 return "姓名:"+this.name+";"+"年龄:"+this.age;
    39 }
    40
    41 public int compareTo(Person person)
    42 {
    43 if(this.age>person.age)
    44 {
    45 return 1;
    46 }else if(this.age<person.age){
    47 return -1;
    48 }else{
    49 return 0;
    50 }
    51 }
    52 }

    程序运行结果:

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

    从程序的运行结果中可以发现,重复的”王五“对象只有一个;”赵六“和”孙七“年龄重复,但是”孙七“并没有加入到集合中。这是由于采用了比较器造成的,因为比较器操作时如果某个属性没有进行比较的指定,则也会认为是同一个对象,所以此时应该在Person类的compareTo方法中增加按姓名比较。

    修改Person比较器
    package com.yuchao.collection;

    import java.util.Set;
    import java.util.TreeSet;

    public class TreeSetDemo {

    /**
    *
    @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    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);
    }

    }

    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 person)
    {
    if(this.age>person.age)
    {
    return 1;
    }
    else if(this.age<person.age){
    return -1;
    }
    else{
    return this.name.compareTo(person.name);
    }
    }
    }

    程序输出结果:

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

    以下程序运行结果出现了”孙七",而且去掉了重复的内容,但此时的重复内容去掉,并不是真正意义上的去掉重复元素。因为此时靠的是Comparable接口完成的,而如果换成HashSet则也会出现重复的内容,所以要想真正的去掉重复元素,则必须深入研究Object类。

    提示:想要判断对象是否重复必须覆盖Object类中的equals()方法,但同时必须覆盖hashCode()方法,此方法表示一个哈希编码,一般哈希码是通过公式进行计算的,可以将类的全部属性进行适当计算,以求出一个不会重复的哈希码。

    修改equals()、hashCode()去除重复元素
    package com.yuchao.collection;

    import java.util.HashSet;
    import java.util.Set;

    public class TreeSetDemo {

    /**
    *
    @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    //Set<Person> allSet=new TreeSet<Person>();
    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);
    }

    }

    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 boolean equals(Object object)
    {
    if(this==object)
    {
    return true;
    }
    if(!(object instanceof Person))
    {
    return false;
    }
    Person person
    =(Person)object;
    if(this.name.equals(person.name)&&this.age==person.age)
    {
    return true;
    }
    else
    {
    return false;
    }
    }

    public int hashCode()
    {
    return this.name.hashCode()*this.age;
    }

    }
    提示:在实际开发中经常会碰到区别同一对象的问题,所以,一个完整的类最好覆写Object类的hashCode()、equals()、toString()3个方法。

  • 相关阅读:
    java支持跨平台获取cpuid、主板id、硬盘id、mac地址 (兼容windows、Linux)
    Oracle 数据导入导出
    Linux下通过脚本自动备份Oracle数据库并删除指定天数前的备份
    Liunx下查看服务器硬件信息
    Linux文件类型及如何查看,修改文件读写权限
    Linux ext3 ext4 区别
    网站访问量大 怎样优化mysql数据库
    LeetCode——Coin Change
    LeetCode——two sum
    LeetCode——Edit Distance
  • 原文地址:https://www.cnblogs.com/yuchao/p/1965714.html
Copyright © 2011-2022 走看看