Java集合之HashSet和TreeSet集合

本文深入探讨Java集合框架中的HashSet和TreeSet,解析无序、不重复元素存储特性,及其实现原理。通过实例演示如何去除字符串重复字符,去除集合重复元素,以及利用TreeSet进行自定义对象排序和去重。
摘要由CSDN通过智能技术生成

一、HashSet集合

存储特点:无索引,不可以重复,无序。

无索引、无序:存储结构决定的(树)

不能重复:      HashSet在存储元素时,当存储到相同的元素时,这个元素会被剔除。原因:当用HashSet集合存储元素时,会使用add()方法,该方法会从中调用equals方法来判断下次存储的元素是否相同,而equals方法又是根据对象的hashCode来判断的,当存一个元素时,该元素会分配一个hashCode值,当存入下个相同的元素时,会和前面的hashCode值比较,如果相同,则不能存入。 

       不过在存储自定义对象时,如自定义:student类的对象时,我们认为相同属性的学生为同一个人,但是存储时却不能把相同的学生剔除。因为HashSet在存储对象时,存储的是对象的引用,此时,hashCode值都是不同的。因此,HashSet怎样剔除重复的自定义对象呢?重写hashCode方法,将hashCode值设置为不同的值(默认31)。


LinkedHashSet:底层是用链表实现的,是set集合中唯一一个保证怎么存就怎么取的集合对象, 因为是HashSet的子类,所以也保证了元素的唯一性,与HashSet原理一致 。如果要用Set集合实现有序存储可以用它。

例①:从键盘输入若干个字符,利用Set集合去除字符串中重复的字符

/*
* ①先创建Scanner对象
* ②创建LinkedHashSet对象,将字符存取,去掉重复
* ③将字符串转化为字符数组,存入LinkedHashSet集合中
* */  
Scanner sc = new Scanner(System.in);
        System.out.print("请输入若干字符:");
        LinkedHashSet<Character> lhs = new LinkedHashSet<>();
        String s = sc.nextLine();
        char []arr = s.toCharArray();
        for(char c :arr){
            lhs.add(c);
        }
        System.out.print(lhs);

例②:去除集合中的重复元素

/*  分析:
    *  1、创建list集合存储若干个重复元素
    *  2、单独定义方法去除元素
    *  3、打印list集合
    * */
public class TestRemoveRepeat02 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");

        System.out.print(getSingle(list));
    }
    /*去除list集合中的重复元素
    *1、创建一个LinkedHashSet集合
    * 2、将List集合中所有元素添加到LinkedHashSet集合中
    * 3、将list集合清空
    * 4、将LinkedHashSet集合中的元素添加会List集合
    * */
    public static List  getSingle(List<String> list){
        LinkedHashSet<String> lhs = new LinkedHashSet<>();
        /*for(String c :list){
            lhs.add(c);
        }*/
        lhs.addAll(list);   //不需要遍历,直接用addAll方法
        list.clear();        //将集合清空
        list.addAll(lhs);
        return list;
    }
}

 

二、TreeSet集合

存储特点:无索引,不可以重复

主要作用:    可以利用它对元素进行排序。因为在调用add()方法存储对象时,会默认调用compareTo方法进行比较,同样也保证了存储的唯一性。不过此外:

当compareTo方法返回零的时候只返回一个元素。(根据存储方式,改元素为树的根节点)

当compareTo方法返回正数的时候,集合会顺序存储。(保存在树的右子树) 

当compareTo方法返回负数的时候,集合会倒序存取。(保存在树的左子树)


例①:利用TreeSet集合存储若干个,自定义对象Person(属性有name、age)并根据年龄排序打印出对象。

分析:定一个Personal personal 对象,有name、age属性。因为要根据person.age来判断,默认的compareTo方法定不能满足要求,它只能实现对元素的排序,因此要重写compareTo方法,因此Personal要实现Compare<Personal>接口来实现该功能。

Persnal.java

public class Person implements Comparable<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 + '\'' +
                '}';
    }
    @Override
    public int compareTo(Person o) {
        int num = this.age-o.age;//年龄是比较的主要条件,姓名为次要条件
        return num==0 ? this.name.compareTo(o.name):num;
    }

测试类
public class Demo01_TreeSet {
    public static void main(String[] args) {


        /*TreeSet存储自定义对象*/
        TreeSet<Person> ts = new TreeSet<>();
        ts.add(new Person("张三",23));
        ts.add(new Person("李四",25));
        ts.add(new Person("王五",26));
        ts.add(new Person("赵六",29));
        ts.add(new Person("张三",23));
        ts.add(new Person("张3",23));
        /*按照年龄排序输出集合*/
        System.out.println(ts);
    }

例②:在一个集合中存储了无序且重复的字符串,定义一个方法,让其有序(字典排序),且不能去重复

public class Test01 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("aaa");
        list.add("cc");
        list.add("ddda");
        list.add("vvvvaaa");
        list.add("ddda");
        sort(list);
        System.out.print(list);
    }
    /*
    * 定义方法:排序且去重复
    * 1、创建TreeSet集合对象,因为TreeSet集合本身具备比较功能
    * 2、将List集合中的所有元素添加到TreeSet集合中,对其排序,保留重复
    * 3、清空List集合
    * 4、将TreeSet集合排好序的集合添加至List集合中
    * */
    public static void sort(List<String> list){
        /*因为用TreeSet集合排序要去重复,因此我们必须重写它的compareTo方法来完成我们想要的功能
        * 我们采取匿名内部类的方式实现
        * */
        TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                int num = s1.compareTo(s2);//比较内容为主要条件
                return num == 0 ? 1 : num;//当两个字符串一样时,我们把compare的值设置为1,使其保存
            }
        });

        ts.addAll(list);
        list.clear();
        list.addAll(ts);
    }
}

例③:可以从键盘输入多个整数,查到输入quit时结束输入。把所有输入的数倒序排列输出

/* 可以从键盘输入多个整数,查到输入quit时结束输入。把所有输入的数倒序排列输出
    * 1、创建scanner对象
    * 2、创建TreeSet集合对象,TreeSet集合中传入比较器
    * 3、不断的接受整数,遇到quit退出.因为退出为quit,所以键盘录入时都以字符串的形式录取
    * 4、判断是quit退出,不是转化为Integer,添加到集合中
    * 5、遍历TreeSet集合
    * */
public class Test03 {
   public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
       System.out.println("请输入数字,回车键为间隔:");
       TreeSet<Integer> ts = new TreeSet<>(new Comparator<Integer>() {
           @Override
           public int compare(Integer i1, Integer i2) {
               int num = i2-i1;
               return num == 0 ? 1 : num;
           }
       });

       while(true){
           String line = sc.nextLine();
           if("quit".equals(line)){
               break;
           }
           try {
               Integer integer = Integer.parseInt(line);
               ts.add(integer);
           }catch (Exception e){
               System.out.println("请输入数字!");
           }
       }
       for(Integer i : ts){
           System.out.println(i);
       }
   }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值