Set集合

Set

HashSet初探

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

        strs.add("asdf");
        strs.add("asdf");
        strs.add("asdf");
        strs.add("asdf");
        strs.add("fdas");
        strs.add("jmjm");
        strs.add("jnjn");

        for (String str : strs) {
            System.out.println(str);
        }
/*
        jmjm
        asdf
        jnjn
        fdas
         */
  1. 存储时的顺序和取出的顺序不同
  2. 不可重复
  3. 放到HashSet集合中的元素实际上是放到HashSet集合的key部分了。

TreeSet初探

二叉树

二叉树

TreeSet集合存储元素的特点:

无序不可重复,但是存储的元素可以自动按照大小顺序排序!称为可排序集合

无序代表没有下标并不是指顺序

        //创建集合
        Set<String> set = new TreeSet<>();

        //添加元素
        set.add("A");
        set.add("F");
        set.add("B");
        set.add("V");
        set.add("C");

        for (String s : set) {
            System.out.println(s);
        }
        /*
        A
        B
        C
        F
        V
         */
  1. TreeSet集合底层实际上是一个TreeMap
  2. TreeMap集合底层是一个二叉树。
  3. 放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了
  4. TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小自动排序。称为:可排序集合。

数据库中有很多数据:

userId name birth


1 zs 1980-11-11

2 ls 1980-10-11

3 ww 1981-11-11

4 zl 1979-11-11

编写程序从数据库当中取出数据,在页面展示用户信息的时候按照生日升序或者降序。这个时候可以使用TreeSet集合,因为TreeSet集合放进去,拿出来就是有顺序的。

//创建一个TreeSet集合
        TreeSet<String> ts = new TreeSet<>();

        //添加String
        ts.add("zhangsan");
        ts.add("lisi");
        ts.add("wangwu");
        ts.add("zhangsi");
        ts.add("wangliu");

        //遍历
        for (String t : ts) {
            //按照字典顺序升序
            System.out.println(t);
        }
        /*
        lisi
        wangliu
        wangwu
        zhangsan
        zhangsi
         */

        //创建第二个TreeSet
        TreeSet<Integer> ts2 = new TreeSet<>();

        //添加元素
        ts2.add(100);
        ts2.add(200);
        ts2.add(300);
        ts2.add(400);
        ts2.add(5400);
        ts2.add(70);
        ts2.add(52);
        ts2.add(1733);

        //遍历
        for (Integer integer : ts2) {
            System.out.println(integer);
        }
        //升序排列
        /*
        52
        70
        100
        200
        300
        400
        1733
        5400
         */
自定义类型排序

对于自定义的对象与类型 ,TreeSet无法排序

以下程序对于Person类型来说,无法排序。因为没有指定Person对象之间的比较规则。

谁大谁小没有一个比较的规则。

会出现错误:java.lang.ClassCastException:

com.javase.collection.Set.Person cannot be cast to java.lang.Comparable

public class TreeSetTest03 {
    public static void main(String[] args) {
        //创建对象
        Person p1 = new Person(12);
        Person p2 = new Person(54);
        Person p3 = new Person(20);
        Person p4 = new Person(25);

        //创建TreeSet集合
        TreeSet<Person> people = new TreeSet<>();

        //添加元素
        people.add(p1);
        people.add(p2);
        people.add(p3);
        people.add(p4);

        //遍历
        for (Person person : people) {
            System.out.println(person);
        }
    }
}
class Person{
    private int age;

    //构造方法
    public Person() {
    }

    public Person(int age) {
        this.age = age;
    }

    //重写toString方法

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

自定义规则

第一种方法:类继承Comparable接口
public class TreeSetTest04 {
    public static void main(String[] args) {
        //创建对象
        Customer c1 = new Customer(12);
        Customer c2 = new Customer(54);
        Customer c3 = new Customer(20);
        Customer c4 = new Customer(25);

        //创建TreeSet集合
        TreeSet<Customer> customers = new TreeSet<>();

        //添加元素
        customers.add(c1);
        customers.add(c2);
        customers.add(c3);
        customers.add(c4);

        //遍历
        for (Customer customer : customers) {
            System.out.println(customer);
        }
    }
}

    //放在TreeSet集合中的元素需要实现java.lang.Comparable接口。
    //并且实现compareTo方法。equals可以不写
class Customer implements Comparable<Customer>{
    private int age;

    //构造方法
    public Customer() {
    }

    public Customer(int age) {
        this.age = age;
    }

        //需要在这个方法中编写比较的逻辑,或者说比较的规则
        //k.compareTo(t.key)
        //拿着参数k和集合中每一个k进行比较,返回值可能是   >0  <0  ==0
        //比较规则最终还是由程序员指定的:例如按照年龄升序。或者按照年龄降序。

    @Override
    public int compareTo(Customer c) { // c1.compareTo(c2)
        //this是c1
        //c是c2
        //c1和c2比较的时候,就是this和c比较
        /*int age1 = this.age;
        int age2 = c.age;
        if (age1 == age2){
            return 0;
        }else if(age1 > age2) {
            return 1;
        }else {
            return -1;
        }*/
        return this.age - c.age; //>0   <0  ==0

    }

    //重写toString方法
    @Override
    public String toString() {
        return "Customer{" +
                "age=" + age +
                '}';
    }
}
//创建对象
        Dog d1 = new Dog("小汪",7);
        Dog d2 = new Dog("小花",7);
        Dog d3 = new Dog("张三",8);
        Dog d4 = new Dog("小安",55);

        //创建集合
        TreeSet<Dog> dogs = new TreeSet<>();

        //添加元素
        dogs.add(d4);
        dogs.add(d2);
        dogs.add(d1);
        dogs.add(d3);

        //遍历
        for (Dog dog : dogs) {
            System.out.println(dog);
        }
public class Dog implements Comparable<Dog>{
    private String name;
    private int age;


    public Dog() {
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

    @Override
    public int compareTo(Dog o) {
        //年龄相同按照名字排序
        //姓名是String类型,可以直接比较。调用compareto来完成比较
        if(this.age == o.age) return this.name.compareTo(o.name);
        //年龄不一样
        return this.age - o.age;
    }
}
第二种方法:使用比较器

Cat对象:

public class Cat {
    private String name;
    private int age;

    //构造方法
    public Cat() {
    }
    public Cat(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;
    }

    //重写toString方法

    @Override
    public String toString() {
        return "小猫咪[" +
                "name='" + name + '\'' +
                ", age=" + age +
                ']';
    }
}

比较器对象:

/*
单独在这里编写一个比较器
比较器实现java.util.Comparator接口。(Comparable是java.lang包下的。Comparator是java.util包下的)
 */
public class CatComparator implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        if (o1.getAge() == o2.getAge())
            return o1.getName().compareTo(o2.getName());
        return o1.getAge() - o2.getAge();
    }
}

测试类:

public class TreeSetTest06 {
    public static void main(String[] args) {
        //创建TreeSet,需要使用这个比较器。
        //TreeSet<Cat> cats = new TreeSet<>(); //这种方式不行 需要在构造方法传递一个比较器进去。创建TreeSet
        TreeSet<Cat> cats = new TreeSet<>(new CatComparator());

        //添加对象
        cats.add(new Cat("小沫",15));
        cats.add(new Cat("小幂",7));
        cats.add(new Cat("小咪",7));
        cats.add(new Cat("小幂",8));
        cats.add(new Cat("小米",7));
        cats.add(new Cat("小米",9));

        //遍历
        for (Cat cat : cats) {
            System.out.println(cat);
        }
    }
}
/*
小猫咪[name='小咪', age=7]
小猫咪[name='小幂', age=7]
小猫咪[name='小米', age=7]
小猫咪[name='小幂', age=8]
小猫咪[name='小米', age=9]
小猫咪[name='小沫', age=15]
 */

使用匿名内部类

 TreeSet<Cat> cats = new TreeSet<>(new Comparator<Cat>() {
            @Override
            public int compare(Cat o1, Cat o2) {
                if (o1.getAge() == o2.getAge())
                    return o1.getName().compareTo(o2.getName());
                return o1.getAge() - o2.getAge();
            }
        } );
降序输出

通过传入比较器让树降序输出

public class TreeSetTest03 {
    public static void main(String[] args) {
        //创建集合
        Set<Integer> set = new TreeSet<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        //添加元素
        set.add(15);
        set.add(17);
        set.add(188);
        set.add(173);

        //遍历
        for (Integer integer : set) {
            System.out.println(integer);
        }
    }
}
总结

Comparable和comparator怎么选择?

​ 当比较规则一成不变的时候,或者说当比较规则只有一个的时候,建议实现Comparable接口

​ 如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。

​ Comparator接口的设计符合OCP原则

OCP原则:软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值