Java集合-Set

简介: Java集合-Set

f7265aca4d731cfd8f6164c87dca3bb5.jpg

Java集合-Set

Set(java.util.Set)接口,Set中存放的一组没有重复数据的集合,换句话说,同样的元素在Set中只能出现一次。Set接口是一个标准的JAVA接口,是Collection的子类,所以Set继承了Collection 的所有特性。可以向Set中添加任何java对象,如果Set不是类型化的,没有使用Java泛型,那么您甚至可以在同一个集合中混合不同类型(类)的对象,实际开发中很少这么做。


Set和List

Set和List非常相似,两个接口都代表着元素的集合,但是也有一些明显的不同。这些差异反映在Set和List接口包含的方法中 ,List中可以存在相同的元素,而Set中不允许有重复的元素。第二个不同是,Set中的元素是没有顺序的,List中的元素是有顺序的,List可以按顺序进行迭代。


Set的例子

下面是简单的Set例子:

package com.jenkov.collections;
import java.util.HashSet;
public class SetExample {
    public static void main(String[] args) {
        Set setA = new HashSet();
        String element = “123”;
        setA.add(element);
        System.out.println( setA.contains(element) );
    }
}


上面例子创建一个HashSet,HashSet是Set接口的一个实现,然后往里面添加一个String对象的元素,添加完后检查是否包含此元素。


Set的实现

作为Collection 子类型,Collection 接口中的所有方法在Set接口中也可用。既然Set是个接口,实例化时就要使用具体的实现类。可以选择下面几个Collections API中的实现:

  • java.util.EnumSet
  • java.util.HashSet
  • java.util.LinkedHashSet
  • java.util.TreeSet

在迭代集合时,每一个集合实现在元素的顺序以及在集合中插入和访问元素所需的时间(big O表示法)方面的行为都略有不同。HashSet由HashMap支持,它不保证迭代元素时元素的顺序。LinkedHashSet 和HashSet 是不一样的,LinkedHashSet 可以保证元素的顺序与添加元素时的顺序一样,重新插入LinkedHashSet中已存在的元素不会更改此顺序。TreeSet 同样可以保证元素的迭代顺序,但是元素的顺序是排序后的顺序,换句话就是顺序是调用了 Collections.sort() 后的顺序,这个顺序由它们的自然顺序决定(如果它们实现了Comparable的话),或者由一个特定的Comparator 实现来确定。Set在java.util.concurrent中也有一些实现类,这个以后会讲述。


创建Set

下面是创建 Set实例:

package com.jenkov.collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetExample {
    public static void main(String[] args) {
        Set setA = new HashSet();
        Set setB = new LinkedHashSet();
        Set setC = new TreeSet();
    }
}


Set的泛型

默认可以在Set中添加Object,Java5以后新加了泛型,可以限制Set集合中的数据类型,下面是例子:

Set<MyObject> set = new HashSet<MyObject>();
Set中只能添加MyObject实例对象,访问或者迭代时不需要强制类型转换:
for(MyObject anObject : set){
   //do someting to anObject...
}


Set添加元素

可以通过add()方法向Set中添加元素,这个方法继承自Collection.下面是例子:

Set<String> setA = new HashSet<>();
setA.add("element 1");
setA.add("element 2");
setA.add("element 3");

调用了三次add()方法。


迭代Set元素

有两种方法迭代Set:

  • 使用Iterator迭代 Set
  • 使用 for-each 循环

这两种方法下面都会讲述,迭代元素的顺序取决于使用的Set实现类。

使用Iterator迭代Set

使用Iterator迭代Set,首先需要从Set中获取Iterator,下面是例子:

Set<String> setA = new HashSet<>();
setA.add("element 1");
setA.add("element 2");
setA.add("element 3");
Iterator<String> iterator = set.iterator();
while(iterator.hasNext(){
  String element = iterator.next();
}

使用For-Each循环迭代Set

第二种方式是使用for-each循环迭代Set,下面是代码:

Set set = new HashSet();
for(Object object : set) {
    String element = (String) object;
}

Set接口实现了Iterable接口,所以Set可以使用for-each循环迭代,如果Set使用了泛型,那么迭代循环内部可以使用泛型的类型 :

Set<String> set = new HashSet<>();
for(String str : set) {
    System.out.println(str);
}

使用Stream API迭代Set

第三种方式是使用 Stream API迭代Set ,迭代时必须从Set中获取Stream,下面是代码:

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");
Stream<String> stream = set.stream();
stream.forEach((element) -> { System.out.println(element); });


从Set中移除元素

可以通过Set的remove(Object o)方法,从Set中移除一个元素,下面是例子:

set.remove("object-to-remove");

没有办法更加Set的索引删除元素,因为元素的顺序取决于Set的具体实现。


从Set中移除所有元素

可以调用Set的clear()方法,移除Set中所有的元素:

set.clear();


将另外一个集合的所有元素加到Set中

List接口中一个addAll()方法,可以增加 另一个 Collection (List或者Set)中的所有元素到 Set中,Set中也有对应的方法:

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");
Set<String> set2 = new HashSet<>();
set2.add("four");
set2.addAll(set);

代码执行后,set2中包含的元素是one,two , three 和four 。


移除另外一个集合在本集合中存在的所有元素

Set接口中存在removeAll()方法,就移除本集合和给定的Collection中同时存在的元素,在集合论中,这被称为集合与其他集合之间的区别,下面是代码:

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");
Set set2 = new HashSet();
set2.add("three");
set.removeAll(set2);

执行完代码后,set中包含的元素是one 和 two。元素three被移除,因为在set和set2中都存在。


保留两个集合中同时存在的元素

Set接口同样也有保留两个集合中同时存在的元素,也就是两个集合的交集 :

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");
Set<String> set2 = new HashSet<>();
set2.add("three");
set2.add("four");
set.retainAll(set2);

执行完代码后,set中只包含了three元素,因为只有这个元素同时存在set和set2中。


Set大小

可以通过Set的size()方法查看Set的大小:

Set<String> set = new HashSet<>();
set.add("123");
set.add("456");
set.add("789");
int size = set.size();

执行后,size的值是3,因为Set中已经加入了3个元素。


检查Set是否是空

可以调用Set的isEmpty()方法,检查Set是否是空:

Set<String> set = new HashSet<>();
boolean isEmpty = set.isEmpty();

执行代码后isEmpty 的值是空,因为Set中没有元素。也可以通过Set的size()是否是0来判断Set是否是空:

Set<String> set = new HashSet<>();
boolean isEmpty = (set.size() == 0);

执行代码后,isEmpty的值是true,因为Set中没有元素,所以size()的值是0.


Set是否包含某个指定元素

可以通过contains()方法检查Set中是否包含给定的元素,下面是例子:

Set<String> set = new HashSet<>();
set.add("123");
set.add("456");
boolean contains123 = set.contains("123");

执行后contains123的值是true,因为Set中包含字符串123。

为了确定Set中是否包含每个元素,Set内部用的equals()方法比较。但是Set中可以添加null值,所以也可以检查Set中是否包含null:

set.add(null);
containsElement = set.contains(null);
System.out.println(containsElement);

显然,contains()的参数是null, contains()方法比较不使用的==而不是equals()。


将Set转成List

可以通过  List 的 addAll()方法,将Set转成List

Set<String> set = new HashSet<>();
set.add("123");
set.add("456");
List<String> list = new ArrayList<>();
list.addAll(set);

执行后,List中包含 123 和 456。

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