016.day16 HashSet TreeSet 比较器Comparable Comparator

day16笔记

一、HashSet

1. 存储特点

以hashCode排序,不能出现重复元素,相对无序(与输入顺序不相关)

2. 比较规则

首先比较hashCode,相同时调用当前对象的equals方法

  • 如果hashCode相同,equals方法比较不相同,则存储地址发生冲突,顺次后延
  • 如果hashCode相同,equals方法比较相同则为相同元素,不会添加
  • 如果hashCode不同,认定是不同对象,不会调用equals方法比较

3. 哈希结构

  • 在Object中调用native声明的方法计算出一个与内存地址相关的编码
  • 可以在Object的子类中(所有类)重写hashCode方法
  • 通常重写hashCode时将其转换为和对象属性值相关的计算公式
  • 默认的hashCode计算方式使用31作为运算基数主要是出于性能的考虑

二、TreeSet

1. 存储特点

以元素之间的比较结果决定存放的顺序,不能出现重复元素,默认按照自然升序

2. 比较规则

  • 可以盛放实现了自然排序接口的实例,如:基本数据类型包装类,字符串,自定义类型等

  • 当一个TreeSet集合中出现不同类型的元素时,即泛型约束不强烈时,对于每一种类型均要实现自然排序接口,在重写的方法中指定不同类型比较时的结果,例如使用instanceof关键字判断比较对象的实例类型

    		Student student = null;
    		// 1.判断实例的类型
    		if (o instanceof Student) {
    			student = (Student) o;
    		}else {
    			// 如果待比较元素不是Student类型,不予添加
    			return 0;
    		}
    
  • 由于无法改写字符串及包装类中的compareTo方法,所以应避免在TreeSet集合中存入不兼容类型的数据

  • compareTo方法中,使用this关键字代表当前存入集合中的对象,参数列表中的对象为集合中已存在的对象,在得出最终比较结果时可能会发生多次比较

  • 基于二分法的比较规则,逐渐缩小所在元素应在区间

  • 返回0代表标记当前元素为重复元素,不会存入集合

  • 返回正数代表当前元素所处位置应在当前比较元素之后

  • 返回负数代表当前元素所处位置应在当前比较元素之前

3.几个方法

		TreeSet<Integer> treeSet = new TreeSet<>();
		// 排序的时间:添加元素时,通过元素本身值的比较决定相应的属性,compareTo()方法调用
		treeSet.add(50);
		treeSet.add(30);
		treeSet.add(100);
		treeSet.add(20);
		// 输出 20 30 50 100
// treeSet.headSet()
		// 第一个参数为指定的比较基准,不需要是集合中的元素(不包括参数这个元素)
		for (Integer integer : treeSet.headSet(55)) {
			System.out.println(integer); // 20 30 50 (55之前的元素)
		}
// treeSet.tailSet(比较的范围,是否包含-true)
		// 第一个参数为指定的比较基准,不需要是集合中的元素(包括参数这个元素)
		for (Integer integer : treeSet.tailSet(80)) {
			System.out.println(integer);// 100 (80之后的元素)
		}
// treeSet.subSet(起始值,是否包含-true,终止值,是否包含-false)
		// 第一个参数为指定的比较基准,不需要是集合中的元素
		for (Integer integer : treeSet.subSet(20, 40)) {
			System.out.println(integer);//20 30 (左闭右开)
		}

三、比较器

1. Comparable

自然排序接口,重写compareTo方法,使用方法见TreeSet

// 1.实现comparable方法
public class Student implements Comparable<Student>{}
// 2.重写compareTo方法
@Override
	public int compareTo(Student o) {}
//return 0 相同元素不存进去
//return 1;// 正数放后
//return -1;// 负数放前

2. Comparator

外部排序接口,使用匿名内部类的方式实现,指定泛型,并重写compare(paraA,paraB)方法

// 匿名内部类 -> 只能使用一次,不需要更改类本身的结构,比较规则有变动的情况
		// 当同时具有Comparable和Comparator时,以Comparator规则为准
		Set<Person> set = new TreeSet<>(new Comparator<Person>() {
            // 需求:向TreeSet集合当中存放Student对象,使得对象之间根据年龄升序
			@Override
			public int compare(Person newPerson, Person oldPerson) {
            // 第一个参数为新添加进来的对象,第二个参数为集合当中与之比较的对象
				// 当两个对象属性完全相同时,认定是重复对象,返回0
				if (newPerson.getName().equals(oldPerson.getName()) && newPerson.getAge() == oldPerson.getAge()) {
					// 当两个比较对象各属性相同时,认定相同,不予添加
					return 0;
				}
				// 2.年龄的比较
				if (newPerson.getAge() >= oldPerson.getAge()) {
					// 通过正负来决定位置
					// 正数放后
					// 负数放前
					return 1;
				} else {
					return -1;
				}
			}
		});
  • paraA代表当前正在存入的元素
  • paraB代表集合中已存在的元素,有可能发生多次比较
  • 返回0代表标记当前元素为重复元素,不会存入集合
  • 返回正数代表当前元素所处位置应在当前比较元素之后
  • 返回负数代表当前元素所处位置应在当前比较元素之前
原文地址:https://www.cnblogs.com/yokii/p/9417431.html