Java中的Set

本文深入探讨Java集合框架中的HashSet、LinkedHashSet与TreeSet的特点及应用。详细解析了这些集合类如何实现去重,并通过重写hashCode和equals方法来确保对象唯一性。此外,还介绍了如何利用TreeSet进行数据排序。
摘要由CSDN通过智能技术生成
set(接口):
特点:无序(无下标) 不重复

HashSet添加字符串:
//  HashSet 主要用来去重
public static void fun() {
    //  创建一个HashSet
    HashSet<String> set = new HashSet<>();
    boolean b1 = set.add("d");
    boolean b2 = set.add("d");
    set.add("a");
    set.add("a");
    set.add("b");
    set.add("b");
    set.add("c");
    set.add("c");
    //  有序 怎么存 怎么打印
    System.out.println(b1);
    System.out.println(b2);
    System.out.println(set);
}

HashCode及equals的重写:
public class Person {
    private String name;
    private int age;
    public Person() {
        super();
    }
    public Person(String name, int age) {
        super();
        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;
    }
    public String toString() {
        return "姓名:" + name + ", 年龄:" + age;
    }
    /*
    //  重写equals方法
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        System.out.println("你猜猜 我执行了吗?");
        //  名字相同 和 年龄相同 就是同意对象      
        Person person = (Person)obj;
        return this.name.equals(person.getName()) && this.age == person.getAge();
    }

    //  重写HashCode方法
    //  Set集合在进行存储时
    //  HashCode值相同 
    //  会调用equals方法 进行对比 是同一对象就不存
    //  HashCode值不相同时没有调用equals方法 直接存
    //  思考:如何提高存储效率?(少调几次equals方法进行比对)
    @Override
    public int hashCode() {
        // TODO Auto-generated method stub
        final int num = 15;
        return this.name.hashCode() * num + this.age;
    }
    */

    //  之后使用系统自动生成的HashCode和equals
    @Override
    public int hashCode() {
        //  31是个质数
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    //  判断两个对象 是否相同
    @Override
    public boolean equals(Object obj) {
        //  如果两地址一样 返回true
        if (this == obj)
            return true;
        //  如果传进对象为空 返回false
        if (obj == null)
            return false;
        //  如果两对象不是一个类创建 返回false
        if (getClass() != obj.getClass())
            return false;
        //  向下转型(准备调用特有的方法)
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;           
        } else if (!name.equals(other.name))//  使用字符串类的比较 判断字符串是否相同
            return false;
        return true;
    }
}

//  创建一个HashSet 添加6个人 两两一样
public static void fun() {
    //  HashSet 如何自定义对象类型 如何去重?
    //  通过重写对象类的 equals方法和HashCode方法 来去重
    HashSet<Person> set = new HashSet<>();
    set.add(new Person("张三", 17));
    set.add(new Person("张三", 17));
    set.add(new Person("李四", 18));
    set.add(new Person("李四", 18));
    set.add(new Person("王五", 19));
    set.add(new Person("王五", 19));  
    //  遍历set集合 查看去重结果
    Iterator<Person> iterator = set.iterator();
    while(iterator.hasNext()) {
        Person person = iterator.next();
        System.out.println(person);
    }
}

练习:
//  编写一个程序,获取10个1至20的随机数,要求随机数不能重复
public static void fun() {
    HashSet<Integer> set = new HashSet<>();
    //  集合长度小于10 添加
    while (set.size() < 10) {
        //  随机数
        int num = (int)(Math.random() * (20 - 1 + 1) + 1);
        //  添加到集合中
        set.add(num);// 自动装箱
    }
    System.out.println(set);
}

LinkedHashSet:
public static void fun() {
    //  LinkedHashSet是HashSet的一个子类
    //  特点:有序 怎么存怎么取
    //  字符串为什么直接放进set中能去重?
    LinkedHashSet<String> set = new LinkedHashSet<>();
    set.add("l");
    set.add("w");
    set.add("w");
    set.add("a");
    set.add("n");
    set.add("g");
    System.out.println(set);
}

练习:
//  输入一个字符串,去掉其中重复字符
public static void fun() {
    System.out.println("请输入一个字符串:");        
    Scanner scanner = new Scanner(System.in);
    String string = scanner.nextLine();
    LinkedHashSet<Character> set = new LinkedHashSet<>();
    //  字符串转字符数组
    char[] charArray = string.toCharArray();
    //  添加到set集合中 完成去重
    for (int i = 0; i < charArray.length; i++) {
        set.add(charArray[i]);//  自动装箱
    }
    scanner.close();
    System.out.println(set);
}
//  利用set集合 去除ArrayList集合中的重复元素
//  (操作原ArrayList)
public static void fun() {
    ArrayList<String> list = new ArrayList<>();
    list.add("a");
    list.add("a");
    list.add("b");
    list.add("b");
    list.add("c");
    list.add("c");
    list.add("d");
    list.add("d");
    //  创建set
    LinkedHashSet<String> set = new LinkedHashSet<>();
    //  将list中所有元素 扔到set中
    set.addAll(list);

    /* 方法二
    for (int i = 0; i < list.size(); i++) {
        set.add(list.get(i));
    }
    */
    //  清空原list
    list.clear();
    //  再把set中的所有元素 扔list中
    list.addAll(set);
    //  打印
    System.out.println(list);
}

TreeSet:
特点:无序 不重复 无下标
主要作用:排序
Comparable(接口):
public class Worker extends Person implements Comparable<Worker> {
    public Worker() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Worker(String name, int age) {
        super(name, age);
        // TODO Auto-generated constructor stub
    }

    //  实现接口中的唯一方法
    /*
     * 返回0时 set只有一个元素
     * 1(正数) 按存进去顺序 正序打印
     * -1(负数) 按存进去顺序 倒序打印
     * 
     * TreeSet 按二叉树保存
     * 要保存的数比我小 放在我的左边(返回负数)
     * 要保存的数比我大 放在我的右边(返回正数)
     * 要保存的数一样大 不存储
     * 打印按从小到大输出(升序)
     * 
     * 使用TreeSet排序的步骤
     * 1.让TreeSet集合中保存的对象 实现Comparable接口
     * 2.实现compareTo方法
     * 3.在compareTo方法中 实现 你要排序的规则
     */
    /*
    @Override
    public int compareTo(Worker o) {
        //  按年龄比较
        return this.getAge() - o.getAge();
    }
    */

    /*
    //  按姓名进行排序
    @Override
    public int compareTo(Worker o) {
        // TODO Auto-generated method stub
        return this.getName().compareTo(o.getName());
    }
    */

    //  比较的主要条件 按年龄
    //       次要条件 按姓名
    /*
    @Override
    public int compareTo(Worker o) {
        int num = this.getAge() - o.getAge();// 主要
        if (num != 0) {
            return num;
        }else {
            return this.getName().compareTo(o.getName());
        }
        return num == 0 ? this.getName().compareTo(o.getName()) : num;//    次要
    }
    */

    /* 比较规则
     * 主要笔字符串长度
     * 然后比年龄
     * 最后比字符串
     */
    @Override
    public int compareTo(Worker o) {
        //  比较字符串长度
        int length = this.getName().length() - o.getName().length();
        //  长度一样比年龄
        int num = length == 0 ? this.getAge() - o.getAge() : length;    
        //  年龄一样 比字符串
        return num == 0 ? this.getAge() - o.getAge() : num; 
    }
}

public static void fun() {
    //  创建TreeSet集合 保存4个工人
    //  系统给你留了接口Comparable 如果你想通过TreeSet来排序
    //  你就是显现这个接口 编写排序的规则 系统就会按规则来给你排序
    TreeSet<Worker> set = new TreeSet<>();
    set.add(new Worker("张三", 24));
    set.add(new Worker("李四", 24));
    set.add(new Worker("王五", 23));
    set.add(new Worker("赵六", 27));
    for (Worker worker : set) {
        System.out.println(worker);
    }
    System.out.println((int)'张');
    System.out.println((int)'李');
    System.out.println((int)'王');
    System.out.println((int)'赵');
}

Comparator(接口):
/* 
 * 使用比较器来排序步骤
 * 1.创建一个类 实现Comparator接口
 * 2.实现接口中的方法 并编写 比较的规则
 * 3.把该类的对象 传入 TreeSet集合中
 */
//  保留重复的字符串 的比较器
class KeepStringComImpl implements Comparator<String> {
    //  保留重复的字符串
    @Override
    public int compare(String o1, String o2) {
        int length = o1.length() - o2.length();
        int num = length == 0 ? o1.compareTo(o2) : length;
        //  存与不存 就取决于这个方法的返回值 0就不存
        //  返回1也行 -1也行
        return num == 0 ? 1 : num;
    }
}

public static void fun3() {
    //  保留重复的字符串
    TreeSet<String> set = new TreeSet<>(new KeepStringComImpl());
    set.add("asd");
    set.add("asde");
    set.add("asdef");
    set.add("a");
    set.add("asd");
    System.out.println(set);
}

/*
 * 键盘接收一个字符串 程序对其中所有字符进行排序
 * 要求保留重复的
 */
class KeepCharImpl implements Comparator<Character> {
    @Override
    public int compare(Character o1, Character o2) {
        int num = o1.compareTo(o2);
        return num == 0 ? 1 : num;
    }
}

public static void fun4() {
    System.out.println("请输入一个字符串:");
    Scanner scanner = new Scanner(System.in);
    String string = scanner.nextLine();
    char[] charArray = string.toCharArray();
    //  创建容器 进行排序
    TreeSet<Character> set = new TreeSet<>(new KeepCharImpl());
    for (int i = 0; i < charArray.length; i++) {
        set.add(charArray[i]);
    }
    scanner.close();
    System.out.println(set);
}

/*
 * 程序启动后 可以从键盘输入接收多个整数 
 * 直到输入quit时结束输入 把所有输入的整数倒序排列打印
 * 保留重复 比较器实现
 */
class KeepIntImpl implements Comparator<Integer> {
    @Override
    public int compare(Integer o1, Integer o2) {
        int num = o1 - o2;
        return -(num == 0 ? 1 : num);
    }
}

public static void fun5() {
    Scanner scanner = new Scanner(System.in);   
    //  创建一个TreeSet
    TreeSet<Integer> set = new TreeSet<>(new KeepIntImpl());
    while (true) {
        System.out.println("请输入整数 输入quit结束:");
        String string = scanner.nextLine();
        if (string.equals("quit")) {
            break;
        }
        //  输入的是整数的时候
        int num = Integer.parseInt(string);
        //  添加到容器内 排序
        set.add(num);
    }
    scanner.close();
    //  打印集合
    System.out.println(set);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值