zoukankan      html  css  js  c++  java
  • 77.Java集合之TreeSet

      TreeSet

    案例:使用TreeSet集合存储字符串元素,并遍历

    import java.util.TreeSet;
    
    public class Demo5 {
        public static void main(String[] args) {
            TreeSet ts = new TreeSet();
            ts.add("ccc");
            ts.add("aaa");
            ts.add("ddd");
            ts.add("bbb");
    
            System.out.println(ts); // [aaa, bbb, ccc, ddd]
    
        }
    }
    ---| Itreable      接口 实现该接口可以使用增强for循环
                    ---| Collection        描述所有集合共性的接口
                        ---| List接口        有序,可以重复,有角标的集合
                                ---| ArrayList   
                                ---|  LinkedList
                        ---| Set接口        无序,不可以重复的集合
                                ---| HashSet  线程不安全,存取速度快。底层是以hash表实现的。
                                ---| TreeSet  红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。

    红-黑树

    红黑树是一种特定类型的二叉树

    红黑树算法的规则: 左小右大。

    既然TreeSet可以自然排序,那么TreeSet必定是有排序规则的。

    1:让存入的元素自定义比较规则。

      

    2:给TreeSet指定排序规则。

    方式一:元素自身具备比较性

    元素自身具备比较性,需要元素实现Comparable接口,重写compareTo方法,也就是让元素自身具备比较性,这种方式叫做元素的自然排序也叫做默认排序。

    方式二:容器具备比较性

    当元素自身不具备比较性,或者自身具备的比较性不是所需要的。那么此时可以让容器自身具备。需要定义一个类实现接口Comparator,重写compare方法,并将该接口的子类实例对象作为参数传递给TreeMap集合的构造方法。

    注意:当Comparable比较方式和Comparator比较方式同时存在时,以Comparator的比较方式为主;

    注意:在重写compareTo或者compare方法时,必须要明确比较的主要条件相等时要比较次要条件。(假设姓名和年龄一直的人为相同的人,如果想要对人按照年龄的大小来排序,如果年龄相同的人,需要如何处理?不能直接return 0,因为可能姓名不同(年龄相同姓名不同的人是不同的人)。此时就需要进行次要条件判断(需要判断姓名),只有姓名和年龄同时相等的才可以返回0.)

    通过return 0来判断唯一性。

    问题:为什么使用TreeSet存入字符串,字符串默认输出是按升序排列的?因为字符串实现了一个接口,叫做Comparable 接口.字符串重写了该接口的compareTo 方法,所以String对象具备了比较性.那么同样道理,我的自定义元素(例如Person类,Book类)想要存入TreeSet集合,就需要实现该接口,也就是要让自定义对象具备比较性.

    存入TreeSet集合中的元素要具备比较性.

    比较性要实现Comparable接口,重写该接口的compareTo方法

    TreeSet属于Set集合,该集合的元素是不能重复的,TreeSet如何保证元素的唯一性

    通过compareTo或者compare方法中的来保证元素的唯一性。

    添加的元素必须要实现Comparable接口。当compareTo()函数返回值为0时,说明两个对象相等,此时该对象不会添加进来。

    比较器接口

    ----| Comparable
                   compareTo(Object o)     元素自身具备比较性
    ----| Comparator
                   compare( Object o1, Object o2 )    给容器传入比较器

    TreeSet集合排序的两种方式:

    一,让元素自身具备比较性。

    也就是元素需要实现Comparable接口,覆盖compareTo 方法。

    这种方式也作为元素的自然排序,也可称为默认排序。

    年龄按照搜要条件,年龄相同再比姓名。

    import java.util.TreeSet;
    
    public class Demo4 {
        public static void main(String[] args) {
            TreeSet ts = new TreeSet();
            ts.add(new Person("aa", 20, "男"));
            ts.add(new Person("bb", 18, "女"));
            ts.add(new Person("cc", 17, "男"));
            ts.add(new Person("dd", 17, "女"));
            ts.add(new Person("dd", 15, "女"));
            ts.add(new Person("dd", 15, "女"));
    
    
            System.out.println(ts);
            System.out.println(ts.size()); // 5
    
        }
    }
    
    class Person implements Comparable {
        private String name;
        private int age;
        private String gender;
    
        public Person() {
    
        }
    
        public Person(String name, int age, String gender) {
    
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
    
        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;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        @Override
        public int hashCode() {
            return name.hashCode() + age * 37;
        }
    
        public boolean equals(Object obj) {
            System.err.println(this + "equals :" + obj);
            if (!(obj instanceof Person)) {
                return false;
            }
            Person p = (Person) obj;
            return this.name.equals(p.name) && this.age == p.age;
    
        }
    
        public String toString() {
            return "Person [name=" + name + ", age=" + age + ", gender=" + gender
                    + "]";
        }
    
        @Override
        public int compareTo(Object obj) {
            
            Person p = (Person) obj;
            System.out.println(this+" compareTo:"+p);
            if (this.age > p.age) {
                return 1;
            }
            if (this.age < p.age) {
                return -1;
            }
            return this.name.compareTo(p.name);
        }
    
    }

    二,让容器自身具备比较性,自定义比较器。

    需求:当元素自身不具备比较性,或者元素自身具备的比较性不是所需的。

    那么这时只能让容器自身具备。

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

    并将该接口的子类对象作为参数传递给TreeSet集合的构造函数。

    当Comparable比较方式,及Comparator比较方式同时存在,以Comparator

    比较方式为主。

    import java.util.Comparator;
    import java.util.TreeSet;
    
    public class Demo5 {
        public static void main(String[] args) {
            TreeSet ts = new TreeSet(new MyComparator());
            ts.add(new Book("think in java", 100));
            ts.add(new Book("java 核心技术", 75));
            ts.add(new Book("现代操作系统", 50));
            ts.add(new Book("java就业教程", 35));
            ts.add(new Book("think in java", 100));
            ts.add(new Book("ccc in java", 100));
    
            System.out.println(ts); 
        }
    }
    
    class MyComparator implements Comparator {
    
        public int compare(Object o1, Object o2) {
            Book b1 = (Book) o1;
            Book b2 = (Book) o2;
            System.out.println(b1+" comparator "+b2);
            if (b1.getPrice() > b2.getPrice()) {
                return 1;
            }
            if (b1.getPrice() < b2.getPrice()) {
                return -1;
            }
            return b1.getName().compareTo(b2.getName());
        }
    
    }
    
    class Book {
        private String name;
        private double price;
    
        public Book() {
    
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public Book(String name, double price) {
    
            this.name = name;
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Book [name=" + name + ", price=" + price + "]";
        }
    
    }

    TreeSet练习

    将字符串中的数值进行排序。

    例如String str="8 10 15 5 2 7";    2,5,7,8,10,15

    使用 TreeSet完成。

              思路:1,将字符串切割。

                     2,可以将这些对象存入TreeSet集合。         

                     因为TreeSet自身具备排序功能。

    public class Demo5 {
        public static void main(String[] args) {
            String str = "8 10 15 5 2 7";
            String[] strs = str.split(" ");
            TreeSet ts = new TreeSet();
            for (int x = 0; x < strs.length; x++) {
                int y = Integer.parseInt(strs[x]);
                ts.add(y);
            }
            System.out.println(ts);
        }
    }

    2.   LinkedHashSet

    会保存插入的顺序。

    看到array,就要想到角标。

    看到link,就要想到first,last。

    看到hash,就要想到hashCode,equals.

    看到tree,就要想到两个接口。Comparable,Comparator。

    练习:去除数组中的重复元素.

    author@nohert
  • 相关阅读:
    97. Interleaving String
    96. Unique Binary Search Trees
    95. Unique Binary Search Trees II
    94. Binary Tree Inorder Traversal
    odoo many2many字段 指定打开的form视图
    docker sentry 配置文件位置
    postgres 计算时差
    postgres 字符操作补位,字符切割
    postgres判断字符串是否为时间,数字
    odoo fields_view_get
  • 原文地址:https://www.cnblogs.com/gzgBlog/p/13605318.html
Copyright © 2011-2022 走看看