java中Set集合

java中Set集合

/**
 * Set:元素不可以重复,是无序的
 * Set接口中的方法和Collection一致
 *  Set有两个最重要的子类HashSet,TreeSet
 * HashSet:内部数据哈希表,是不同步的,它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
 *         如何保证该集合的元素唯一性呢?
 *         是通过对象的hashCode()和equals()方法来完成对象唯 一性的
 *         如果对象的hashCode()值不同,那么不用判断equals方法,就直接存储到哈希表中
 *         如果对象的hashCode值相同,那么要再次判断对象 的equals方法是否为true
 *         如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
 *
 *         记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
 *         一般情况 下,如果定义的类会产生很多对象 ,比如 人,学生,书,通常都 需要覆盖equals,hashCode方法。
 *         建立对象判断是否相同的依据
 * TreeSet:可以对Set集合中的元素进行指定顺序的排序。是不同步 的。
 *         判断元素唯一性的方式 :就是根据比较方法comperTo(),返回结果是否是0,是0,就是相同元素,则不往里存储
 *
 *         
  TreeSet对元素进行排序的方式 一:
*           让元素自身具备比较功能,元素需要实现 Comparable接口,重写compeareTo方法

 *           如果不要按照对象中具备 的自然顺序进行排序,如果对象 中不具备 自然顺序,怎么办?
*           可以使用TreeSet集合第二种排序方式 二:
*           让集合自身具备比较功能,定义一个类实现 Comparator接口,重写compare方法
*           将该 类对象作为参数传递给TreeSet集合的构造函数
* * LinkedHashSet是HashSet的子类,它是有序的,且不可重复 *///arrayList判断元素是否相同 remove(),contains(),的依据是equals()方法,//HashSet的依据是hashCode()和equals()方法,该元素是否有和该容器中的元素相同//所以对于自定义对象,如果利用ArrayList容器进行存储,一定要重写equals()方法,//所以对于自定义对象,如果利用HastSet容器进行存储,一定要重写HashCode()和equals()方法,//往HashSet集合中存储Person对象,如果姓名和年龄相同,视为同一个人,视为相同元素
public class Person implements Comparable {

    private String name;
    private int age;

    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 int hashCode() {//判断hash值是否相同

//        System.out.println(this+"......hashcode...");
        return name.hashCode() + age;
    }

    @Override
    public boolean equals(Object obj) {//判断内容是否相同
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Person)) {
            throw new ClassCastException("类型转换错误");
        }
//        System.out.println(this + "......equals...." + obj);
        Person person = (Person) obj;
        return this.name.equals(person.name) && this.age == person.age;
    }


    @Override
    public String toString() {
        return name + ":" + age;
    }

    @Override
    public int compareTo(@NonNull Object o) {
        Person person = (Person) o;
        //主要是按年龄排序,如果年龄相同,根据姓名进行自然排序
  int temp = this.age - person.age;
return temp == 0 ? this.name.compareTo(person.name) : temp;
 }
}
//HashSetDemo
public class HashSetDemo {
public static void main(String[] args) {
HashSet hashSet = new HashSet();
//下面使用LinkedHashSet,它是有序的,不可重复的
// HashSet hashSet = new LinkedHashSet();

 
hashSet.add(new Person("aaa", 10));
 hashSet.add(new Person("bbb", 20));
 hashSet.add(new Person("bbb", 20));
 hashSet.add(new Person("ccc", 30));
hashSet.add(new Person("ccc", 30));
 Iterator iterator = hashSet.iterator();
 while (iterator.hasNext()) {
 Person person = (Person) iterator.next();
 System.out.println(person.getName() + "," + person.getAge());
 }
 }
}//TreeSetDemo
public class TreeSetDemo {
    public static void main(String[] args){
        demo1();
        demo2();
    }
    //存自定义对象
    private static void demo2() {
        TreeSet treeSet = new TreeSet();
        treeSet.add(new Person("zhangsan", 10));
        treeSet.add(new Person("lisi", 20));
        treeSet.add(new Person("wangwu", 20));
        treeSet.add(new Person("wangwu", 20));
        treeSet.add(new Person("zhaoliu", 30));
        treeSet.add(new Person("zhouqi", 30));

        Iterator iterator = treeSet.iterator();
        while (iterator.hasNext()) {
            Person person = (Person) iterator.next();
            System.out.println(person.getName() + "," + person.getAge());
        }
    }
    //存字符串
    private static void demo1() {
        TreeSet treeSet = new TreeSet();
        treeSet.add("aaa");
        treeSet.add("nbb");
        treeSet.add("ecc");
        treeSet.add("gcc");
        treeSet.add("kdd");
        Iterator iterator = treeSet.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}
//方式 二 Comparator的运用,它的原理是二叉树
* 创建了一个根据Person类的name进行排序的比较器
 */

public class ComparatorByName implements Comparator {

    @Override
    public int compare(Object o, Object t1) {
        Person person = (Person) o;
        Person person1 = (Person) t1;

        int temp = person.getName().compareTo(person1.getName());
        return temp == 0?person.getAge()-person1.getAge():temp;
//        return 1;//这样是有序排,怎么存,怎么取
//        return -1;//这样是有序排,怎么存,反过来取
    }
}
//下面是运用自定义比较器,存自定义对象
private static void demo2() {
    TreeSet treeSet = new TreeSet(new ComparatorByName());//这样存进去Person类就不用实现Comparable接口
    treeSet.add(new Person("zhangsan", 10));
    treeSet.add(new Person("lisi", 20));
    treeSet.add(new Person("wangwu", 20));
    treeSet.add(new Person("wangwu", 20));
    treeSet.add(new Person("zhaoliu", 30));
    treeSet.add(new Person("zhouqi", 30));

    Iterator iterator = treeSet.iterator();
    while (iterator.hasNext()) {
        Person person = (Person) iterator.next();
        System.out.println(person.getName() + "," + person.getAge());
    }
}

//对字符串长度进行比较排序
public class ComparatorByLength implements Comparator {
    @Override
    public int compare(Object o, Object t1) {
        String s1 = (String) o;
        String s2 = (String) t1;

        int temp = s1.length()-s2.length();
        return temp==0?s1.compareTo(s2):temp;
    }
}
//运用字符串长度进行比较排序   存字符串

private static void demo1() {
    TreeSet treeSet = new TreeSet(new ComparatorByLength());
    treeSet.add("aaa");
    treeSet.add("nbbdd");
    treeSet.add("ecdc");
    treeSet.add("gcad");
    treeSet.add("kdeterfd");
    Iterator iterator = treeSet.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
}




<think>好的,用户想要寻找关于JavaSet集合的经典代码示例和练习。我需要先回忆一下Set集合的基本概念和常用实现类,比如HashSet、TreeSet和LinkedHashSet。根据引用内容,用户可能已经了解Set的基本特性,比如不允许重复元素,以及如何通过比较器或自然排序来排序元素。 首先,我应该提供一些基础的代码示例,展示如何创建Set、添加元素、遍历等操作。比如使用HashSet的简单例子,然后引入TreeSet的自然排序和定制排序。引用中提到需要比较器类,所以可能需要演示如何实现Comparator接口。 接下来,用户可能需要更复杂的练习,比如去重、集合运算(交集、并集、差集)或者结合泛型使用。引用中的泛型方法示例可能相关,可以展示如何在Set中使用泛型。 还要考虑实际应用场景,比如统计单词数量,处理学生成绩排名等。这些例子能帮助用户理解Set的实际用途。同时,引用中提到的TreeMap可能需要稍微提及,但重点应放在Set上。 需要确保代码语法正确,符合用户提供的引用中的格式。比如,比较器类的实现,自然排序通过Comparable接口,以及使用Lambda表达式简化代码。此外,用户可能需要了解线程安全的Set,所以可以提到ConcurrentSkipListSet,并给出示例。 最后,生成相关问题,帮助用户进一步学习,比如性能分析、线程安全的选择、比较器与Comparable的区别等。这些问题应基于提供的引用和常见的学习难点。 现在,整理这些思路,分步骤给出示例代码,并确保每个例子都有注释说明,符合用户的要求。同时,引用相关的引用内容,比如比较器类和自然排序的实现,以增强答案的可靠性。</think>以下是一些Java Set集合的经典代码示例和练习,结合了基础操作、应用场景和进阶技巧: ### 一、基础操作示例 1. **HashSet去重** ```java Set<String> cities = new HashSet<>(); Collections.addAll(cities, "北京", "上海", "广州", "北京", "深圳"); System.out.println(cities); // 输出:[北京, 上海, 广州, 深圳] 自动去重[^3] ``` 2. **TreeSet自然排序** ```java Set<Integer> scores = new TreeSet<>(); scores.add(85); scores.add(90); scores.add(78); System.out.println(scores); // 输出:[78, 85, 90] 自动排序 ``` ### 二、对象排序实践 3. **实现Comparable接口(自然排序)** ```java class Student implements Comparable<Student> { String name; int score; @Override public int compareTo(Student o) { return Integer.compare(this.score, o.score); // 按分数排序 } } Set<Student> stuSet = new TreeSet<>(); stuSet.add(new Student("王五", 90)); stuSet.add(new Student("李四", 85)); // 自动按分数升序排列 ``` 4. **使用Comparator定制排序**(引用[2]的Comparator实现) ```java Set<String> words = new TreeSet<>((s1, s2) -> s2.length() - s1.length()); // 按字符串长度降序排列 words.add("apple"); words.add("banana"); words.add("cat"); System.out.println(words); // 输出:[banana, apple, cat][^2] ``` ### 三、集合运算练习 5. **集合交集/并集/差集** ```java Set<Integer> setA = new HashSet<>(Arrays.asList(1,2,3)); Set<Integer> setB = new HashSet<>(Arrays.asList(2,3,4)); // 交集 setA.retainAll(setB); // 结果:[2,3] // 并集 setA.addAll(setB); // 结果:[1,2,3,4] // 差集 setA.removeAll(setB); // 结果:[1] ``` ### 四、高级应用示例 6. **统计单词频率** ```java String text = "this is a test text test"; Set<String> uniqueWords = new HashSet<>(Arrays.asList(text.split(" "))); System.out.println("Unique words count: " + uniqueWords.size()); ``` 7. **线程安全的有序集合** ```java Set<String> concurrentSet = new ConcurrentSkipListSet<>(); concurrentSet.add("A"); concurrentSet.add("C"); concurrentSet.add("B"); System.out.println(concurrentSet); // 保持线程安全的有序状态 ``` ### 推荐练习方向 1. 实现一个去重且保留插入顺序的集合(LinkedHashSet) 2. 编写比较器实现多字段排序(先按年龄降序,再按姓名升序) 3. 使用Stream API操作Set集合 4. 实现两个超大集合的高效交集运算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值