Java—Set集合(HashSet、TreeSet)

简介: 今天来看看Java集合中的Set集合,为什么Set集合中元素不能重复?为什么Set集合是无序的?我们来共同交流交流

今天来看看Java集合中的Set集合,为什么Set集合中元素不能重复?为什么Set集合是无序的?我们来共同交流交流


d5a8d51ce40b61dfc8ccc3cf6d418ef7.png


Set集合的概述


特点


元素不可重复(相同内容不会被加入,没有下标)


无序(存进去是这个顺序,取出来就不一定是这个顺序)(Set容器可以与数学中的“集合”的概念相对应)


Set接口是Collection的子接口,Set接口没有提供额外的方法,但实现Set接口的容器类中的元素是没有有顺序的,而且不可以重复。


Set容器类:HashSet、TreeSet


继承和实现情况


  • TreeSet实现AbstractSet类


  1. 实现NavigableSet接口:使用导航方法扩展的 SortedSet,报告给定搜索目标的最接近匹配。方法lower、floor、ceiling和higher分别返回小于、小于或等于、大于或等于和大于给定元素的元素,如果没有这样的元素则返回null。可以按升序或降序访问和遍历 NavigableSet。


  • 实现Cloneable接口:向 Object.clone() 方法指示该方法可以合法地对该类的实例进行逐个字段的复制。在未实现 Cloneable 接口的实例上调用 Object 的 clone 方法会导致抛出异常 CloneNotSupportedException。


  • 实现 java.io.Serializable接口:未实现此接口的类将不会对其任何状态进行序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于识别可序列化的语义。


实际应用


import java.util.HashSet;
import java.util.Set;
public class SetTest {
    public static void main(String[] args){
        Set s = new HashSet();
        s.add("hello");
        s.add("world");
        s.add(new Name("f1","f2"));
        s.add(new Integer(100));
        s.add(new Name("f1","f2")); //相同的元素不会被加入
        s.add("hello");  //相同的元素不会被加入
        System.out.println(s);
    }
}


输出结果:[100,hello,world,f1 f2]


import java.util.Set;
import java.util.HashSet;
public class SetTest2 {
    public static void main(String[] args){
        Set s1=new HashSet();
        Set s2 =new HashSet();
        s1.add("1");
        s1.add("b");
        s1.add("c");
        s2.add("d");
        s2.add("a");
        s2.add("b");
        //Set和List容器类都具有Constructor(Collection c)
        //构造方法用以初始化容器类
        Set sn = new HashSet(s1);
        sn.retainAll(s2);
        Set su = new HashSet(s1);
        su.addAll(s2);
        System.out.println(sn);
        System.out.println(su);
    }
}


输出结果:


[a,b]


[d,a,c,b]


下面我们来具体说说HashSet和TreeSet的使用吧~


HashSet


有什么特点吗?


  • 不可重复
  • 无序的,即不会记录插入的顺序
  • 可以存不同类型数据
  • 集合元素可以存null(但只能存储一个null值)


方法有哪些?


add:添加元素


remove:删除元素


contains:判断是否包含某个元素


clear:清空


Iterator:使用迭代器遍历集合


foreach:遍历集合


实战演练


import java.net.SocketOption;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetTest {
    public static void main(String[] args) {
        //实例化一个HashSet集合
        Set set = new HashSet();
        //添加元素
        set.add(1);
        set.add("a");
        System.out.println(set);
        //删除元素
        set.remove(1);
        System.out.println(set);
        //判断是否包含某个元素
        System.out.println(set.contains(1));
        //清空集合
        set.clear();
        System.out.println(set);
        set.add("a");
        set.add("b");
        set.add("c");
        set.add("d");
        set.add("d");  //重复的元素不会被添加
        set.add(null);  //可以存取空值
        System.out.print(set);
        //使用迭代器遍历集合
        Iterator it =set.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
        //for each迭代集合
        for (Object obj:set){//把set的每一个值取出来,赋值给obj,直到循环完set的所有值
            System.out.println(obj);
        }
        System.out.println(set.size());  //获取集合的元素个数
    }
}


如果想要让集合只能存同样类型的对象,怎么做呢?实例化时就指定出具体数据类型


//使用泛型
Set<String> set1 = new HashSet<String>();
set1.add("a");
set1.add("123");


注:可能很多小伙伴发现自己添加的元素有重复内容,但集合自动去重了,Set的去重原理是什么?这里有一篇还不错的博客,可以转战观看:Java笔记 —— Set集合的去重原理(源码分析)_一纸春秋的博客-CSDN博客_java set 去重原理


TreeSet


有什么特征吗?


  • 有序(底层在添加元素的时候会自动进行排序)
  • 可以对元素进行排序(自然排序(默认)、定制排序)


为什么TreeSet的存储结构是有序的?


在进行add添加元素的时候底层会进行一个逻辑判断,如果要新添加的元素在集合中存在,则该集合的元素保持;如果要添加的元素在集合中不存在,则将元素添加到集合中,并且进行自然排序:


TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序排列


  • 如果this>obj,返回正数1
  • 如果this<obj,返回正数-1
  • 如果this=obj,返回0,则认为这两个对象相等


必须放入同样类的对象。(默认会进行排序)否则可能会发生类型转换异常,我们可以使用泛型来进行限制


方法有哪些?


add:添加元素


remove:删除元素


contains:判断是否包含某个元素


clear:清空


实战演练


自然排序


import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<Integer>();
        //TreeSet自然排序
        set.add(5);
        set.add(2);
        set.add(4);
        set.add(3);
        System.out.println(set);   //输出结果为2 3 4 5
        //删除元素
        set.remove(5);
        //判断是否包含某个元素
        set.contains(3);
        //清空集合
        set.clear();
        //使用迭代器遍历集合
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //for each迭代集合
        for (Integer i:set){
            System.out.println(i);
        }
    }
}


定制排序


在创建TreeSet集合对象时,提供一个Comparator接口的实现类对象。由该Comparator对象负责集合元素的排序逻辑


import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
    public static void main(String[] args) {
        //-------------------------------------
        Person p1 = new Person("唐三",21);
        Person p2 = new Person("小舞",21);
        Person p3 = new Person("戴沐白",25);
        Person p4 = new Person("奥斯卡",24);
        Person p5 = new Person("朱竹清",20);
        Person p6 = new Person("宁荣荣",19);
        Person p7 = new Person("马红俊",26);
        Set<Person> personSet = new TreeSet<Person>(new Person());
        personSet.add(p1);
        personSet.add(p2);
        personSet.add(p3);
        personSet.add(p4);
        personSet.add(p5);
        personSet.add(p6);
        personSet.add(p7);
        for(Person p:personSet){
            System.out.println(p.name+"  "+p.age);
        }
    }
}
class Person implements Comparator<Person> {
    String name ;
    int age;
    public Person(){}
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    //自己定制的比较方法,调用这个方法来判断age
    public int compare(Person o1,Person o2){
        if(o1.age>o2.age){
            return 1;
        }else if(o1.age<o2.age){
            return -1;
        }else{
            return 0;
        }
    }
}


输出结果为:


d9b764ba835edc301cfa0c4fb7ce9dd8.png

相关文章
|
6天前
|
存储 算法 Java
Java Set深度解析:为何它能成为“无重复”的代名词?
Java的集合框架中,Set接口以其“无重复”特性著称。本文解析了Set的实现原理,包括HashSet和TreeSet的不同数据结构和算法,以及如何通过示例代码实现最佳实践。选择合适的Set实现类和正确实现自定义对象的hashCode()和equals()方法是关键。
18 4
|
6天前
|
Java
那些与Java Set擦肩而过的重复元素,都经历了什么?
在Java的世界里,Set如同一位浪漫而坚定的恋人,只对独一无二的元素情有独钟。重复元素虽屡遭拒绝,但通过反思和成长,最终变得独特,赢得了Set的认可。示例代码展示了这一过程,揭示了成长与独特性的浪漫故事。
13 4
|
6天前
|
Java 开发者
Java Set:当“重复”遇见它,秒变“独宠”!
在Java编程中,Set接口确保集合中的元素不重复,每个元素都是独一无二的“独宠”。本文介绍了Set的两种常见实现:HashSet和TreeSet。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet基于红黑树实现,不仅去重还能对元素进行排序。通过示例代码,展示了这两种集合的具体应用,帮助开发者更好地理解和使用Set。
13 4
|
8天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
16 2
|
7天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
11天前
|
存储 Java 开发者
Java Set:无序之美,不重复之魅!
在Java的集合框架中,Set接口以其“无序之美”和“不重复之魅”受到开发者青睐。Set不包含重复元素,不保证元素顺序,通过元素的hashCode()和equals()方法实现唯一性。示例代码展示了如何使用HashSet添加和遍历元素,体现了Set的高效性和简洁性。
24 4
|
11天前
|
存储 算法 Java
为什么Java Set如此“挑剔”,连重复元素都容不下?
在Java的集合框架中,Set是一个独特的接口,它严格要求元素不重复,适用于需要唯一性约束的场景。Set通过内部数据结构(如哈希表或红黑树)和算法(如哈希值和equals()方法)实现这一特性,自动过滤重复元素,简化处理逻辑。示例代码展示了Set如何自动忽略重复元素。
19 1
|
11天前
|
存储 算法 Java
Java中的Set,你真的了解它的“无重复”奥秘吗?
在Java的广阔天地里,Set以其独特的“无重复”特性,在众多数据结构中脱颖而出。本文将揭秘Set的“无重复”奥秘,带你领略其魅力。Set通过哈希算法和equals()方法协同工作,确保元素不重复。通过一个简单的案例,我们将展示HashSet如何实现这一特性。
22 1
|
12天前
|
存储 Java 开发者
在 Java 中,如何遍历一个 Set 集合?
【10月更文挑战第30天】开发者可以根据具体的需求和代码风格选择合适的遍历方式。增强for循环简洁直观,适用于大多数简单的遍历场景;迭代器则更加灵活,可在遍历过程中进行更多复杂的操作;而Lambda表达式和`forEach`方法则提供了一种更简洁的函数式编程风格的遍历方式。
|
12天前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
12 0