JAVA集合03_HashSetLinkedHashSet概述TreeSet自然顺序比较器顺序

Posted 所得皆惊喜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA集合03_HashSetLinkedHashSet概述TreeSet自然顺序比较器顺序相关的知识,希望对你有一定的参考价值。

文章目录

①. HashSet的概述

  • ①. 无序性!=随机性(正在的无序性是指元素在底层存储的位置是无序的)

  • ②. 不可重复性:当向set中添加进相同的元素的时候,后面的这个不能添加进去

  • ③. 没有带索引的方法,所以不能用普通for循环遍历

  • ④. 底层数据结构是哈希表

		HashSet<String>hs=new HashSet<>();
		boolean b1=hs.add("a");
		boolean b2=hs.add("a");
		hs.add(null);
		//[null, a]
		System.out.println(hs);  //HashSet的继承体系中,有重写toString()方法
		System.out.println(b1);//true
		System.out.println(b2);//false
		//只要能用迭代器迭代的,就可以使用增强for循环遍历
		for(String str:hs)
		    System.out.println(str);//[null,a]
		

②. 哈希值的介绍

  • ①. 哈希值是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

  • ②. Object类中有一个方法可以获取对象的哈希值
    public int hashCode():返回对象的哈希码值

  • ③. 特点:

  1. 同一个对象多次调用hashCode() 方法返回的哈希值是相同的
  2. 默认情况下,不同对象的哈希值是不相同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
  • ④. 哈希值原理

  • ⑤. 自定义对象的唯一性
  1. 要求添加进Set中的元素所在的类,一定要重写equal()和 hashCode()方法,进而保存不可重复性
  2. hashCode():属性相同的对象返回值必须相同,属性不同的返回值尽量不同(提高效率)
  3. equals():属性相同返回true,属性不同返回false,返回false的时候就存储
[ 掌握关于equals方法和hashCode方法底层实现原理 ]
    /*
  public static int hashCode(Object a[]) 
        if (a == null)
            return 0;
        int result = 1;
        for (Object element : a)
            result = 31 * result + (element == null ? 0 : element.hashCode());
        return result;
    
   为什么是31?
   1.31是质数,质数是能被1和它本身整除的数
   2.31这个数既不大也不小
   3.31这个数好算,2的5次方-1,向左移动5位数-1
  * */
    @Override
    public boolean equals(Object o) 
        if (this == o) return true;//调用的对象和传入的对象是同一个对象,直接返回true
        if (o == null || getClass() != o.getClass()) return false;//传入的对象为空或者字节码文件不相同,返回false
        Person person = (Person) o;//向下转型
        return age == person.age &&
                Objects.equals(name, person.name);
        //如果调用对象的年龄和传入对象的年龄 相同并且 调用对象的姓名和传入对象的姓名相同返回true
    

  • ⑥. HashSet的原理:当HashSet调用add()方法储存对象的时候,先调用对象的hashCode方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象。如果没有哈希值相同的对象就直接存入集合;如果有哈希值相同的对象,就和哈希值相同对象逐个进行equals()比较,比较结果为false就存入,true则不存

③. LinkedHashSet存取有序

  • ①. 哈希表和链表实现的Set接口,具有可预测的迭代次序

  • ②. 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的

  • ③. 由哈希表保证元素唯一,也就是说没有重复的元素

    @Test
	public void testLinkHashSet()
		Set set=new LinkedHashSet();
		set.add(123);
		set.add(456);
		set.add("AAA");
		set.add("BBB");
		set.add(null);
		Iterator iterator=set.iterator();
		while(iterator.hasNext())
			System.out.println(iterator.next());//123 456 AAA BBB null
		
  • ④.去除list中重复的元素
   //将集合中重复的元素去掉
    @Test
    public void fun7()
    ArrayList<String>list=new ArrayList<>();
    list.add("AAA");
    list.add("AAA");
    list.add("AAA");
    list.add("AAA");
    list.add("AAA");
    list.add("AAA");
    list.add("BBB");
    list.add("BBB");
    list.add("CCC");
    list.add("CCC");
    getSingle(list);
    // 打印
        System.out.println(list);
    

    public static  void getSingle(ArrayList<String> list) 
        /*LinkedHashSet<String>lhs=new LinkedHashSet<>();
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext())
            lhs.add(iterator.next());
        

        for(String lhs2:lhs)
            System.out.print(lhs2+"\\t");
        */
       //1.创建一个LinkedHashSet集合
        LinkedHashSet<String>lhs=new LinkedHashSet<>();
        //2.将List集合中所有的元素添加到LinkedHashSet集合
        lhs.addAll(list);
        //3.将List 集合中元素清除
        list.clear();
        //4.将LinkedHashSet集合中的元素添加到List集合中
        list.addAll(lhs);
    

④. TreeSet - 排序

  • ①. .TreeSet的特点:元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
  1. TreeSet():根据其元素的自然排序进行排序
  2. TreeSet(Comparator comparator):根据指定的比较器进行排序
  • ②. 没有带索引的方法,所以不能使用普通for循环遍历

  • ③. 由于是Set集合,所以不包含重复元素的集合

  • ④. 向TreeSet添加属性,需要添加同一类型的属性

⑤. 自然顺序(Comparable)

  • ①. TreeSet类的add()方法中会把存入的对象提升为Comparable类型

  • ②. 调用对象的CompableTo()方法和集合中的对象比较

  • ③. 根据CompableTo()方法返回的结果进行储存

  • ④. TreeSet底层是一个二叉树,两个叉。小的存储在左边(负数),大的存储在右边(正数),相等就不存0。CompareTo方法,在TreeSet集合如何存储元素取决于compareTo方法的返回值

  1. 返回的0,集合中只有一个元素
  2. 返回-1,集合会将存储的元素倒序
  3. 返回1,集合会怎么存就怎么取
public class TreeSetDemo 
    public static void main(String[] args) 
        TreeSet<Person> ts=Sets.newTreeSet();
        ts.add(new Person("张三",23));
        ts.add(new Person("李四",13));
        ts.add(new Person("唐志",13));
        ts.add(new Person("王五",43));
        ts.add(new Person("赵六",33));
        //[Person(name=李四, age=13), Person(name=张三, age=23), Person(name=赵六, age=33), Person(name=王五, age=43)]
        System.out.println(ts);
    

@Data
@AllArgsConstructor
class Person implements Comparable
    private String name;
    private Integer age;
    //按照年龄从小到大排序
    public int compareTo(Object o) 
        Person p=(Person)o;
        int num=this.age-p.age;//年龄是比较的主要条件
        //int num=-this.age-p.age;//年龄从大到小排序
        return num==0?this.name.compareTo(p.name):num;//姓名是比较的次要条件
    

  • ⑤. 按照姓名长度进行排序
public class TreeSetDemo 
    public static void main(String[] args) 
        TreeSet<Person> ts=Sets.newTreeSet();
        ts.add(new Person("张三",23));
        ts.add(new Person("李四",13));
        ts.add(new Person("李四",12));
        ts.add(new Person("王五",43));
        ts.add(new Person("赵六",33));
        System.out.println('张'+0);//24352
        System.out.println('李'+0);//26446
        System.out.println('王'+0);//29579
        System.out.println('赵'+0);//36213
        //[Person(name=张三, age=23), Person(name=李四, age=12), Person(name=李四, age=13), Person(name=王五, age=43), Person(name=赵六, age=33)]
        System.out.println(ts);
    

@Data
@AllArgsConstructor
class Person implements Comparable
    private String name;
    private Integer age;
    
    //按照姓名进行排序,相同按照年龄进行排序
    public int compareTo(Object o) 
        Person p=(Person)o;
        int num=this.name.compareTo(p.name);
        return num==0?this.age-p.age:num;
    


⑥. 比较器顺序(Comparator)

  • ①. 创建TreeSet的时候可以制定一个Comparator接口

  • ②. 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序

  • ③. 调用的对象是Comparator接口中compare()方法顺序

  • ④. 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

    @Test
    public void fun4()
        /*
        需求:将字符串按照长度排序
        * */
        //Comparator c=new CompareByLen();
        //new TreeSet(Comparator );
        TreeSet<String>ts=new TreeSet<>(new CompareByLen());
        ts.add("aaaaaaaa");
        ts.add("z");
        ts.add("wc");
        ts.add("nba");
        ts.add("cba");
        System.out.println(ts);//[n, bb, aaa]
    
    class CompareByLen /* extends Object*/implements Comparator<String>//
        @Override
        public int compare(String s1, String s2) 
            //按照字符串长度进行比较
            int num=s1.length()-s2.length();//长度为主要条件
            return num==0?s1.compareTo(s2):num;//内容为次要条件
        
    

⑦. 两种排序比较

  • ①. 自然顺序(Comparable)
  1. TreeSet 类的add()方法中会把存入的对象提升为Comparable类型
  2. 调用对象的CompableTo()方法和集合中的对象比较
  3. 根据CompableTo()方法返回的结果进行储存
  • ②. 比较器顺序(Comparator)
  1. 创建TreeSet的时候可以制定一个Comparator接口
  2. 如果传入了Comparator的子类对象,那么TreeSet就会按照比较器中的顺序排序
  3. 调用的对象是Comparator接口中compare()方法顺序
  4. 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
  • ③. 两种方式的区别
  1. TreeSet如果传入Comparator,就优先按照Comparator
  2. TreeSet构造函数什么都不传,默认按照类中Comparable的顺序(没有就报错ClassCastE xception)
//java.lang.ClassCastException: com.itheima.TreeSetDemo4.Person cannot be cast to java.base/java.lang.Comparable
public class Person 
    private String name;
    private int age;

    public Person()
    public Person(String name, int age) 
        this.name = name;
        this.age = age;
    

    public String getName() 
        return name;
    

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

    public int getAge() 
        return age;
    

    public void setAge(int age) 
        this.age = age;
    

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


    @Test
    public void fun1()
        //1.按照年龄来排序
        TreeSet<Person>ts=new TreeSet<>();
        ts.add(new Person("张三",23));
        ts.add(new Person("张三",23));
        ts.add(new Person("张三",23));
        ts.add(new Person("李四",24));
        ts.add(new Person("王五",24));
        System.out.println("ts = " + ts);
    

以上是关于JAVA集合03_HashSetLinkedHashSet概述TreeSet自然顺序比较器顺序的主要内容,如果未能解决你的问题,请参考以下文章

Groovy03_集合

读Java8函数式编程笔记03_高级集合类和收集器

读Java实战(第二版)笔记03_引入和使用流

如何使用 mongoDb java 异步驱动程序插入 mongoDb 集合后获取 _id

day03_02 集合操作

03_set集合