java数据结构(红黑树)set集合 HashSet HashSet三个问题 LinkedHashSetTreeSet TreeSet集合默认规则排序规则

数据结构(红黑树)

在这里插入图片描述
在这里插入图片描述

红黑规则

在这里插入图片描述
后代节点就是比如13根结点 13下面的8和17上的都是后代叶节点
简单路径就是比如随便一个13到8到11到nil就是一个简单路径.但是如果出现13到8然后再8回13再13到8这就不是简单路径了

红黑树添加结点规则

在这里插入图片描述

set集合

在这里插入图片描述

  public static void main(String[] args) {

        Set<String>s=new HashSet<>();


        s.add("张三");
        s.add("李思");
        s.add("王五");
        s.add("老刘");
        //添加元素不能重复 如果重复了打印无结果
        //细节:add有返回值 会先判断这个元素添加过没有


        //打印
        Iterator<String> iterator = s.iterator();
        while (iterator.hasNext()){
            iterator.next();

        }
        System.out.println(s);//[张三, 李思, 王五, 老刘]


        //增强for遍历
        for (String s1 : s) {
            System.out.print(s1);//张三李思王五老刘
        }

        System.out.print("________________");
        //lambda表达式

        s.forEach(new Consumer<String>() {
            @Override
            public void accept(String s2) {
                System.out.print(s2);
            }
        });
        //lambda简化
        s.forEach(s3-> System.out.print(s3));
    }

小结

在这里插入图片描述
简单记忆:hash:杂乱->无序;linked:链锁->有序;tree:树->可排序

HashSet

在这里插入图片描述
在这里插入图片描述

哈希值:对象的整数表现形式
哈希碰撞发生的概率特别小可以不计.

 public static void main(String[] args) {


        //创建对象
        Student s1=new Student("张三",18);
        Student s2=new Student("张三",18);

        //System.out.println(s1.hashCode());//488970385
        //System.out.println(s2.hashCode());//1209271652
        //这是没有重写hash方法 不同对象计算出的哈希值不同


        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
        //24022538
        //24022538
        //重写了hash方法 不同对象只要属性值相同计算出的哈希值也相同
        
    }

在这里插入图片描述

hash表保证元素统一的方法.当要添加一个新元素的时候,发现要添加的位置有元素而且是链表挂了两个,挨个进行equals进行比较,如果都不一样才会添加新的元素.如果比较第三个发现第三个一样,要添加的元素会舍弃不存

加载因子0.75就是扩容时机,以这个题为例,当数组存入16×0.75=12个元素的时候这个数组就会扩容至原先的两倍
在这里插入图片描述

当链表的长度过长大于8而且数组长度大于等于64当前链表会自动转化为红黑树

HashSet三个问题

HashSet为什么没有索引因为底层的结构不唯一(就是有时候用链表存数据有时候用的红黑树),结构太多导致于确定索引比较困难,所以舍弃了索引机制
HashSet利用什么机制保证去重重写equals方法和Hash方法
HashSet为什么存和取的顺序不一样因为存入数据的时候可能会用到链表和红黑树的方式所以取的时候也是按照他们的规则存取的
HashSet添加元素的过程2、新元素排在老元素后面

LinkedHashSet

在这里插入图片描述

每一个元素都记录当前元素地址值和后一个元素的地址值所以说他是有序的

   public static void main(String[] args) {

        Student s1=new Student("张三",18);
        Student s2=new Student("王五",13);
        Student s3=new Student("李四",14);
        Student s4=new Student("张三",18);


        java.util.LinkedHashSet<Student>lhs=new java.util.LinkedHashSet<>();

        System.out.println(lhs.add(s1));
        System.out.println(lhs.add(s2));
        System.out.println(lhs.add(s3));
        System.out.println(lhs.add(s4));

        System.out.println(lhs);
        //true
        //true
        //true
        //false
        //[Student{name = 张三, age = 18}, Student{name = 王五, age = 13}, Student{name = 李四, age = 14}]
    }

它可以保证数据的存取顺序

小结

TreeSet

在这里插入图片描述

  public static void main(String[] args) {

        //利用TreeSet存储整数并进行排序

        java.util.TreeSet<Integer>ts=new java.util.TreeSet<>();


        ts.add(2);
        ts.add(1);
        ts.add(3);
        ts.add(4);

        //打印集合
        System.out.println(ts);//[1, 2, 3, 4]


        //遍历集合

        //迭代器
        Iterator<Integer> it = ts.iterator();
        while(it.hasNext()){
            Integer i = it.next();
            System.out.println(i);

        }


        System.out.println("_____________");


        //增强for
        for (Integer t : ts) {
            System.out.println(t);
        }


        System.out.println("_____________");

        //lambda
        ts.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        });



    }

TreeSet集合默认规则

排序规则挨个比较各个字母,如果出现一个比另外下面的大的后面就不用看了

排序规则(第一种排序方法)

在这里插入图片描述
在这里插入图片描述

自定义对象如果未实现接口那么排序报错
实现接口需要自定义对象实现Comparable接口 接口下重写抽象方法compareTo方法 底层就是采用一个红黑树比较

方式二

在这里插入图片描述

练习

帮助理解什么时候使用第一种什么时候使用第二种
需求存入四个字符串 按照长度排序,如果一样长则按照首字母排序
String默认是按顺序排序但是不符合要求这时候就用到了第二种排序比较器排序

    public static void main(String[] args) {

        // 按照长度排序,如果一样长则按照首字母排序
        TreeSet<String>ts=new TreeSet<>(new Comparator<String>() {
            @Override
            //o1表示当前要添加的元素
            //o2表示已经在红黑树存在的元素
            public int compare(String o1, String o2) {
                //按照长度排序

                int i=o1.length()-o2.length();

                //如果长度相同则按照字母
                i=i==0?o1.compareTo(o2):i;
                //解读: i等于0吗如果等于o就是用默认的compare方法.如果不等于0那就是i
                return i;
            }
        });


        ts.add("c");
        ts.add("ab");
        ts.add("df");
        ts.add("qwer");


        System.out.println(ts);
        //[ab, c, df, qwer]这是默认的排序方式使用的是compareTo


        System.out.println(ts);//[c, ab, df, qwer]
//这是使用第二个排序方法后的到的
        

    }

小练

在这里插入图片描述

 @Override
    public int compareTo(Student o) {
        int  sumO=o.getChineseGrade()+o.getMathGrade()+o.getEnglishGrade();
        int totalScore=this.getChineseGrade()+this.getMathGrade()+getEnglishGrade();

        //totalScore表示当前总分
        //sumO表示o的总分


        int i=totalScore-sumO;


        i=i==0?this.chineseGrade-this.getChineseGrade():i;
//这句意思是如果总分一样 比较语文成绩
        i=i==0?this.getMathGrade()-this.getMathGrade():i;
       //如果语文成绩一样比较数学成绩
       i=i==0?this.getEnglishGrade()-this.getEnglishGrade():i;
      //如果数学成绩一样比较英语成绩
      i=i==0?this.getAge()-this.getAge():i;
      //如果英语成绩一样比较年龄
        i=i==0?this.getName().compareTo(o.getName()):i;
       //如果年龄一样按照名字字母排序

       return i;
       
    }
public static void main(String[] args) {

        //首先创建五个学生对象
        Student s1=new Student("zhangsan",13,60,70,80);
        Student s2=new Student("lsii",15,63,79,68);
        Student s3=new Student("wangwu",11,90,75,57);
        Student s4=new Student("neifan",12,46,34,34);
        Student s5=new Student("hebing",16,45,56,62);




        //创建需要使用哪个集合这边采用TreeSet
        TreeSet<Student>ts=new TreeSet<Student>();


        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);


        //System.out.println(ts);
        //选一个排序方式 这边采用第一种默认的

        for (Student t : ts) {
            System.out.println(t);
        }
        //Student{name = neifan, age = 12, chineseGrade = 46, mathGrade = 34, englishGrade = 34}
        //Student{name = hebing, age = 16, chineseGrade = 45, mathGrade = 56, englishGrade = 62}
        //Student{name = lsii, age = 15, chineseGrade = 63, mathGrade = 79, englishGrade = 68}
        //Student{name = zhangsan, age = 13, chineseGrade = 60, mathGrade = 70, englishGrade = 80}
        //Student{name = wangwu, age = 11, chineseGrade = 90, mathGrade = 75, englishGrade = 57}


    }

总结

在这里插入图片描述

总结 集合的使用应该怎么选择

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Java中,Set是一种集合数据结构,它不允许重复元素,并且没有固定的顺序。然而,Java中的TreeSet是一种基于红黑树数据结构Set实现,它可以自定义排序规则TreeSet是一个有序的集合,它维护了一个基于元素值的红黑树结构。默认情况下,TreeSet按照元素的自然顺序进行排序。例如,如果元素是整数,则按照从小到大的顺序排列;如果元素是字符串,则按照字典顺序进行排序。 但是,TreeSet也可以使用自定义的Comparator接口实现来指定排序规则。Comparator接口定义了一个compare()方法,它接受两个参数并返回一个int值。如果第一个参数小于第二个参数,则返回负整数;如果第一个参数大于第二个参数,则返回正整数;如果两个参数相等,则返回0。 例如,我们可以创建一个按照字符串长度进行排序TreeSet,如下所示: ```java TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.length() - o2.length(); } }); treeSet.add("hello"); treeSet.add("world"); treeSet.add("java"); ``` 在这个例子中,我们创建了一个TreeSet并使用了一个自定义的Comparator实现。这个Comparator实现比较两个字符串的长度,并按照长度从小到大的顺序排序。 最终,这个TreeSet中的元素将按照长度从小到大的顺序排列,输出结果为: ``` [java, hello, world] ``` ### 回答2: 在使用Java集合类中的TreeSet时,我们默认使用其自然排序规则对元素进行排序。但有时候,我们需要根据自定义的规则对元素进行排序,这时我们可以使用TreeSet提供的自定义排序方法——Comparator。 Comparator是一个接口,其定义了两个方法,分别是compare()和equals()。其中,compare()方法接收两个参数,分别是要比较的对象x和y,这两个对象需要实现Comparator接口;equals()方法用于比较两个对象是否相等。 假设有一个存放Person对象的TreeSet集合,我们需要根据Person的年龄属性进行升序排序,可以通过以下步骤实现: 1. 定义一个Person类,包含name和age两个属性,以及相应的getter和setter方法; 2. 在Person类中实现Comparator接口,并重写compare()方法,在方法中对年龄属性进行比较; 3. 创建一个TreeSet集合,并在构造函数中传入自定义的Comparator对象; 4. 将多个Person对象添加到TreeSet集合中。 具体的代码实现如下: ``` import java.util.*; class Person implements Comparator<Person> { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public int compare(Person p1, Person p2) { if (p1.getAge() > p2.getAge()) { return 1; } else if (p1.getAge() < p2.getAge()) { return -1; } else { return 0; } } } public class TreeSetDemo { public static void main(String[] args) { TreeSet<Person> set = new TreeSet<Person>(new Person()); set.add(new Person("张三", 28)); set.add(new Person("李四", 20)); set.add(new Person("王五", 25)); for (Person p : set) { System.out.println(p.getName() + " " + p.getAge()); } } } ``` 在代码中,我们定义了一个Person类,它实现了Comparator接口,并重写了compare()方法,根据Person对象的age属性进行比较。在主方法中,我们创建了一个TreeSet集合,并在其中添加了多个Person对象,它们会被按照年龄的升序排序。最后,我们通过foreach循环遍历集合中的所有元素,并输出它们的name和age属性。 需要注意的是,在使用自定义比较器时,如果想要保证集合中没有重复元素,我们还需要在Person类中重写equals()方法,并根据name和age两个属性进行比较。 ### 回答3: 在使用Java集合类中的TreeSet时,数据默认情况下是按照自然顺序进行排序的。但是在某些情况下,我们可能希望按照自己定义的规则进行排序。这时,就需要使用TreeSet的自定义排序规则。 自定义排序规则需要我们实现Comparator接口中的compare方法。该方法用于对实现了Comparable接口的对象进行比较。因此,我们需要在自定义类中实现该接口,并重写其中的compare方法。 接下来,我们以Student类为例,介绍如何实现TreeSet的自定义排序规则。假设我们希望按照学生的分数进行从高到低的排序。 首先,在Student类中实现Comparable接口 public class Student implements Comparable<Student>{ private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } @Override public int compareTo(Student o) { return o.score - this.score; } } 在该类中,我们通过重写compareTo方法,实现了按照学生分数进行排序规则。 接下来,在使用TreeSet时,我们需要传入一个Comparator对象,该对象用于指定TreeSet中元素的排序规则。示例代码如下: TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o2.getScore() - o1.getScore(); } }); 在该代码中,我们通过匿名类的方式实现了Comparator接口,并重写了其中的compare方法。通过该方法,我们指定了从高到低的排序规则。 通过以上的示例代码,我们可以看出,自定义排序规则的具体实现可以根据具体情况进行调整。而在该实现中,我们需要注意以下几点: 1. 实现Comparable接口,用于指定对象的默认排序规则。 2. 实现Comparator接口,在特定情况下自定义排序规则。 3. 在使用TreeSet时,需要传入一个Comparator对象,用于指定排序规则。 以上就是Java集合类之settreeset之自定义排序规则的详细介绍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值