Java类集--------2

Set接口:不允许数据重复

Set接口没有扩充方法

 

Set接口常用子类

 

HashSet(无序存储)

  1. 底层使用哈希表+红黑树
  2. 允许存放null

TreeSet(有序存储):

  1. 底层使用红黑树
  2. 不允许出现空值
  3. 自定义类要想保存到TreeSet中,要么实现Comparable接口,要么向TreeSet传入比较器(Comparator)

 

Comparable接口与Comparator接口区别:

在JAVA 中,若想实现自定义类的比较,提供了以下两个接口

 

Java.lang.Comparable接口(内部比较器)-------排序接口:

若一个类实现了接口,就意味着该类支持排序

存放该类的conllection或数组,可以直接通过Collection.sort()或Arrays.sort进行排序

 

实现了Comparable接口的类可以直接存放在TreeSet或TreeMap中。

 

public int compareTo(T o);

 

返回值三种情况:

 

返回正数:表示当前对象大于目标对象

返回0:表示当前对象等于目标对象

返回负数:表示当前对象小于目标对象

 

Comparator(外部排序接口)---比较灵活

若要控制某个自定义类的顺序,而该类本身不支持排序(类本身没有实现Comparable接口)我们可以建立一个该类的“比较器”来进行排序。比较器实现Comparator接口即可

 

“比较器”:实现了Comparator接口的类作为比较器,通过该比较器来进行类的排序

int compare(T o1, T o2);

返回值与compareTo返回值完全一样

返回正数:O1>O2

返回0:O1=O2

返回负数:O1<O2

实现了Comparator接口进行第三方排序----策略模式,此方法更加灵活,可以轻松改变策略进行第三方的排序算法

 

boolean equals(Object obj);

 

代码如下:

import java.util.*;

class Person{
   private  String   name;
   private  Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

//Person类的比较器
class AscAgeComparator  implements Comparator<Person>{//年龄的升序

    @Override
    public int compare(Person o1, Person o2) {
        return o1.getAge ()-o2.getAge ();
    }
}
public class wl {
    public static void main(String[] args) throws Exception {
        Set<Person> set=new TreeSet<> (new AscAgeComparator ());
        set.add (new Person("",20));
        set.add (new Person("",18));
        System.out.println (set);
           
    }
}
结果:

[Person{name='李', age=18}, Person{name='张', age=20}]

 

final int compare(Object k1, Object k2) {
    return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
        : comparator.compare((K)k1, (K)k2);
}

 

Comparable接口与Comparator接口的关系:

Comparable是排序接口,若一个类实现了Comparable接口,意味着该类支持排序,是一个内部比较器(自己去和别人比)

Comparator接口是比较器接口,类本身不支持排序,专门有若干个第三方的比较器(实现了Comparator接口的类)来进行类的排序,是一个外部比较器(策略模式)

 

 

重复元素的比较:

TreeSet和TreeMap依靠Comparable与Comparator接口来区分重复元素

 

自定义类想要保存在TreeSet或TreeMap中:

  1. 要么该类直接实现Comparable接口,覆写compareTo方法
  2. 要么实现一个比较器传入TreeSet或TreeMap来进行外部比较(为0时,证明数据重复)

 

而HashSet与HashMap并不依赖比较接口。此时要想区分自定义元素是否重复,需要同时覆写equals与hashCode方法。

 

首先覆写equals()方法来判断两个元素内容是否相等

覆写equals方法原则;

  1. 自反性:对于任何非空引用值x,x.equals(x)都应返回true,(自己和自己比,一定是真的)
  2. 对称性:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y),才应返回true
  3. 传递性:对于任何非空引用值x和y和z,如果x.equals(y)返回true,并且y.equals(z)返回true,则x.equals(z)一定返回true
  4. 一致性:对于任何非空引用值x和y,若x与y 的属性没有改变,则多次调用x.equals(y)始终返回true或始终返回false
  5. 非空性:对于任何非空引用值x,x.equals(null)一定返回false

        

 

 

 

先调用Hashcode计算出对象hash码决定存放的数据桶,而后只用equals方法来比较元素是否相等,若相等,则不在放置元素,若equals返回false,则在相同桶之后,使用链表将元素连接起来

 

Object 类提供的Hashcode方法使用对象的地址进行哈希

 

如果要想标识出对象的唯一性,一定需要equals()与hashCode()方法共同调用。

对象判断必须两个方法equals()、hashCode()返回值都相同才判断为相同。

哈希表:优化查找次数

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值