欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java集合之HashSet和TreeSet集合使用

程序员文章站 2022-05-03 23:46:01
一、HashSet集合存储特点:无索引,不可以重复,无序。无索引、无序:存储结构决定的(树)不能重复: HashSet在存储元素时,当存储到相同的元素时,这个元素会被剔除。原因:当用HashSet集合存储元素时,会使用add()方法,该方法会从中调用equals方法来判断下次存储的元素是否相同,而equals方法又是根据对象的hashCode来判断的,当存一个元素时,该元素会分配一个hashCode值,当存入下个相同的元素时,会和前面的hashCode值比较,如果相同,则不能存入。......

一、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);
       }
   }
} 

本文地址:https://blog.csdn.net/sinat_41803693/article/details/108034739