Java集合类中Set类以及HashSet和TreeSet

目录

HashSet

TreeSet 


集合框架中的Set类:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。

HashSet

特点:

  1. 底层数据结构是哈希表。是线程不安全的。不同步。
  2. HashSet是如何保证元素唯一性的呢?                                                                                                                                是通过元素的两个方法,hashCode和equals来完成。
     如果元素的HashCode值相同,才会判断equals是否为true。
     如果元素的hashcode值不同,不会调用equals。 
  3. 对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。

例1:简单应用

class  CollectionDemo {
  public static void main(String[] args) {

    HashSet hs=new HashSet();
    //注意:add()返回的是boolean
    System.out.println(hs.add("java1"));
    System.out.println(hs.add("java1"));
    hs.add("java2");
    hs.add("java3");
    hs.add("java3");
    hs.add("java4");
    Iterator it=hs.iterator();
    while(it.hasNext())
    {
      System.out.println(it.next());
    }
  }
}

例2:往hashSet集合中存入自定对象姓名和年龄相同为同一个人,重复元素。 

 

class  CollectionDemo {
  public static void main(String[] args) {

    HashSet hs=new HashSet();
    hs.add(new Person("a1",11));
    hs.add(new Person("a2",12));
    hs.add(new Person("a3",13));
    hs.add(new Person("a2",12));

    Iterator it=hs.iterator();
    while(it.hasNext())
    {
      Person p=(Person)it.next();
      System.out.println(p.getName()+"..."+p.getAge());
    }
  }
}
class Person
{
  private String name;
  private int age;
  Person(String name,int age)
  {
    this.name = name;
    this.age = age;
  }
  //重写hasCode
  public int hashCode()
  {
    System.out.println(this.name+"....hashCode");
    return name.hashCode()+age;// 保证哈希值的唯一性
  }

  public boolean equals(Object obj)
  {
    if(!(obj instanceof Person))
      return false;
    Person p = (Person)obj;
    System.out.println(this.name+"...equals.."+p.name);
    return this.name.equals(p.name) && this.age == p.age;
  }
  public String getName()
  {
    return name;
  }
  public int getAge()
  {
    return age;
  }
}

从运算结果可以看出来,每次添加进来的元素先计算hashCode,当添加进a2时由于hashCode一样,再比为较是否为同一个对象,调用equals方法。

例3:HashSet对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法

class  CollectionDemo {
  public static void main(String[] args) {

    HashSet hs=new HashSet();
    hs.add(new Person("a1",11));
    hs.add(new Person("a2",12));
    hs.add(new Person("a3",13));
    hs.add(new Person("a2",12));

    System.out.println(hs.contains(new Person("a2",12)));  //包含时,先判断hashCode,在判断equals
    System.out.println(hs.remove(new Person("a1",11)));  //删除时,先判断hashCode,在判断equals

    Iterator it=hs.iterator();
    while(it.hasNext())
    {
      Person p=(Person)it.next();
      System.out.println(p.getName()+"..."+p.getAge());
    }
  }
}
class Person
{
  private String name;
  private int age;
  Person(String name,int age)
  {
    this.name = name;
    this.age = age;
  }
  //重写hasCode
  public int hashCode()
  {
    System.out.println(this.name+"....hashCode");
    return name.hashCode()+age*37;// 保证哈希值的唯一性37是任意值
  }

  public boolean equals(Object obj)
  {
    if(!(obj instanceof Person))
      return false;
    Person p = (Person)obj;
    System.out.println(this.name+"...equals.."+p.name);
    return this.name.equals(p.name) && this.age == p.age;
  }
  public String getName()
  {
    return name;
  }
  public int getAge()
  {
    return age;
  }
}

TreeSet 

  1. 可以对Set集合中的元素进行排序 ;
  2. 底层数据结构是二叉树;
  3. 保证元素唯一性的依据:compareTo方法return 0

               TreeSet排序的第一种方式:让元素自身具备比较性。
                元素需要实现Comparable接口,覆盖compareTo方法。
                这种方式也称为元素的自然顺序,或者叫做默认顺序。

                TreeSet的第二种排序方式。
                当元素自身不具备比较性时,或者具备的比较性不是所需要的。
                这时就需要让集合自身具备比较性。
                在集合初始化时,就有了比较方式。

例1:往TreeSet集合中存储自定义对象学生。想按照学生的年龄进行排序 。

class  TreeSetDemo {
  public static void main(String[] args) {
    TreeSet ts=new TreeSet();
    ts.add(new Student("Mike",10));
    ts.add(new Student("Tom",12));
    ts.add(new Student("Mi",17));
    ts.add(new Student("Jim",10));
    Iterator it=ts.iterator();
    while(it.hasNext())
    {
      Student s=(Student)it.next();
      System.out.println(s.getName()+"..."+s.getAge());
    }
  }
}
class Student implements Comparable//该接口强制让学生具备比较性。
{
  private String name;
  private int age;

  Student(String name,int age)
  {
    this.name = name;
    this.age = age;
  }
  //覆盖compareTo方法。
  public int compareTo(Object obj)
  {
    //return 0; //所有元素相同
    if(!(obj instanceof Student))
      throw new RuntimeException("不是学生对象");
    Student s = (Student)obj;
    //System.out.println(this.name+"....compareto....."+s.name);
    //根据年龄进行排序
    if(this.age>s.age)
      return 1;
    if(this.age==s.age)  //主要条件相同,比较次要条件姓名
    {
      return this.name.compareTo(s.name);  //此处的compareTo为String中的比较方法,按字典顺序比较两个字符串
    }
    return -1;

  }
  public String getName()
  {
    return name;

  }
  public int getAge()
  {
    return age;
  }
}

例2:当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较性。

定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数当两种排序都存在时,以比较器为主

定义一个类,实现Comparator接口,覆盖compare方法。

//按照比较器进行排序
class  CollectionDemo {
  public static void main(String[] args) {
    TreeSet ts=new TreeSet(new MyCompare());
    ts.add(new Student("Mike",10));
    ts.add(new Student("Tom",12));
    ts.add(new Student("Mi",17));
    ts.add(new Student("Aim",10));
    Iterator it=ts.iterator();
    while(it.hasNext())
    {
      Student s=(Student)it.next();
      System.out.println(s.getName()+"..."+s.getAge());
    }
  }
}
class Student implements Comparable//该接口强制让学生具备比较性。
{
  private String name;
  private int age;

  Student(String name,int age)
  {
    this.name = name;
    this.age = age;
  }
  //覆盖compareTo方法。
  public int compareTo(Object obj)
  {
    if(!(obj instanceof Student))
      throw new RuntimeException("不是学生对象");
    Student s = (Student)obj;
    //System.out.println(this.name+"....compareto....."+s.name);
    //根据年龄进行排序
    if(this.age>s.age)
      return 1;
    if(this.age==s.age)  //主要条件相同,比较次要条件姓名
    {
      return this.name.compareTo(s.name);  //此处的compareTo为String中的比较方法,按字典顺序比较两个字符串
    }
    return -1;

  }
  public String getName()
  {
    return name;

  }
  public int getAge()
  {
    return age;
  }
}
class MyCompare implements Comparator
{
  public int compare(Object o1,Object o2)
  {
    Student s1 = (Student)o1;
    Student s2 = (Student)o2;

    int num = s1.getName().compareTo(s2.getName());   //调用String中的compareTo方法,按字典进行排序
    //主要条件相同,判断次要条件
    if(num==0)
    {
			if(s1.getAge()>s2.getAge())
				return 1;
			if(s1.getAge()==s2.getAge())
				return 0;
			return -1;

    }
    return num;
  }
}

 

例3:按照字符串长度排序。(使用比较器排序)

 

class  CollectionDemo {
  public static void main(String[] args) {
    TreeSet ts=new TreeSet(new StrLenComparator());  //将比较器对象作为参数传入集合构造函数中
    ts.add("as");
    ts.add("adf");
    ts.add("dert");
    ts.add("ed");

    Iterator it=ts.iterator();
    while(it.hasNext())
    {
      System.out.println(it.next());
    }

  }
}
//实现Comparator接口
class StrLenComparator implements Comparator
{
  //复写compare方法
  public int compare(Object o1,Object o2)
  {
    String s1=(String)o1;  //向下转
    String s2=(String)o2;
    if(s1.length()>s2.length())
      return 1;
    if(s1.length()==s2.length())
      return s1.compareTo(s2);
    return -1;
  }
}

 注意:使用比较器时,将比较器对象作为参数传入集合构造函数中。

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值