首页 > 其他分享 >set的一些用法和问题

set的一些用法和问题

时间:2024-04-02 15:29:26浏览次数:18  
标签:Set 元素 用法 add set 哈希 集合 一些 treeSet

文章目录

set可以存取重复元素吗

Set接口的实现类,如HashSet、TreeSet、LinkedHashSet等,通常不允许重复元素。当尝试向Set中添加一个已经存在的元素时,Set会忽略这个重复的元素,并不会引发异常。

例如,对于HashSet:

import java.util.HashSet;

public class SetExample {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("apple");
        set.add("banana");
        set.add("apple");  // 重复的元素不会被添加
        System.out.println(set); // 输出: [apple, banana]
    }
}

虽然我们尝试了两次添加"apple",但是HashSet只保留了第一次添加的"apple",而忽略了第二次的添加。

然而,也有一些特殊情况,比如LinkedHashSet,它会保留重复的元素,因为它内部使用了一个双向链表来维护元素的顺序。但是,这并不是Set接口的通用行为。

如果你需要一个可以存储重复元素的集合,你应该使用List接口的实现类,如ArrayList或LinkedList。

HashSet 去除重复元素的具体原理是什么?

HashSet 是 Set 接口的典型实现,它不允许重复元素,其内部是通过哈希表(Hash Table)来实现的。HashSet 去除重复元素的具体原理如下:

  • 哈希表:HashSet 内部使用了一个哈希表(HashMap)来存储元素。哈希表是一种数组和链表的结合体,它可以快速地查找和插入元素。
  • 哈希函数:每个元素(对象)都有一个哈希值,这是通过对象的哈希码(hashCode())方法计算得出的。哈希码是一个整数,用于确定元素在哈希表中的位置。
  • 散列冲突:由于哈希表的大小是有限的,当两个或多个元素的哈希值相同时,就会发生散列冲突。为了解决散列冲突,HashSet 使用链地址法,即在哈希表的同一个位置(即同一个索引)上存储多个元素,形成一个链表。
  • equals() 方法:HashSet 使用 equals() 方法来检查两个对象是否相等。当插入一个新元素时,它会检查哈希表中是否存在具有相同哈希值和 equals() 方法的元素。如果存在,那么这个新元素就是重复的,HashSet 不会将其添加到集合中。
  • 重复元素检查:当插入一个新元素时,HashSet 会先计算新元素的哈希值,然后检查哈希表中是否有元素具有相同的哈希值和 equals() 方法。如果有,那么这个新元素就是重复的,HashSet 不会将其添加到集合中。如果没有,它会将新元素添加到哈希表的对应位置上。

set集合平常用在什么地方

Set集合通常用于以下几种情况:

存储不重复的元素:

  • Set集合不允许重复元素,这使得它非常适合用于存储唯一值,例如用户列表、商品列表等。

保持元素顺序:

  • 如果需要保持元素添加时的顺序,可以使用LinkedHashSet,它内部使用链表来维护元素的插入顺序。

快速查找:

  • 由于Set集合内部使用了哈希表,它可以提供快速的查找操作。

实现各种算法:

  • Set集合可以作为实现其他数据结构和算法的基石,例如在图的邻接表表示中,使用Set来存储与一个顶点相邻的所有顶点。
    并发操作:
  • Set集合在多线程环境中通常用于实现无序的共享数据结构,其中每个线程可以添加或删除元素,而不会影响其他线程的访问。

扩展性:

  • 某些高级数据结构,如TreeSet,允许你以自然顺序或自定义顺序对集合中的元素进行排序。

与泛型结合:

  • 由于Set接口是泛型的,它可以与任何类型的对象一起使用,这使得它具有很强的通用性。

实现特定功能:

  • 某些框架或库可能会使用Set集合来实现特定的功能,如在Java中的java.util.Collections类中,Set集合被用于实现各种数据结构,如PriorityQueue和EnumSet。

在多线程环境中如何正确使用Set集合?

在多线程环境中正确使用Set集合是非常重要的,因为集合操作可能会受到线程安全问题的影响。以下是一些在多线程环境中使用Set集合的最佳实践:

  • 使用Collections.synchronizedSet(): 如果你需要一个线程安全的Set集合,你可以使用Collections.synchronizedSet()方法来包装你的Set对象。这会创建一个线程安全的Set,其所有操作都是同步的。
Set<String> synchronizedSet = Collections.synchronizedSet(new HashSet<String>());
  • 使用CopyOnWriteArraySet: CopyOnWriteArraySet是一个线程安全的Set实现,它允许多个线程并发访问集合。当有写操作(如添加或删除元素)时,它会将原始集合复制一份,在新的集合上进行修改,然后再将新的集合替换原始集合。
Set<String> copyOnWriteSet = new CopyOnWriteArraySet<>();
  • 避免在迭代过程中修改集合: 如果你在迭代Set集合时需要进行修改操作(如添加或删除元素),这可能会导致并发修改异常。因此,你应该避免在迭代过程中修改集合。
  • 使用ConcurrentSkipListSet: 如果你需要一个有序的集合,并且需要线程安全,可以使用ConcurrentSkipListSet。它基于SkipList数据结构,提供线程安全的操作。
  • 使用ConcurrentHashMap作为底层数据结构: 如果你需要一个集合,并且它需要与Map关联,可以使用ConcurrentHashMap作为底层数据结构。它提供了线程安全的Set接口实现。
  • 使用并发集合类库: 如果你需要更高级的并发集合操作,可以使用专门的并发集合类库,如Guava的BlockingQueue和BlockingSet。
  • 使用List作为替代: 在某些情况下,如果你需要一个线程安全的Set,但允许重复元素,你可以考虑使用List集合,并通过其他机制来处理重复性。
  • 避免在集合操作中使用Iterator的remove()方法: Iterator的remove()方法不是线程安全的,如果在多线程环境中使用,可能会导致数据不一致。

如何使用TreeSet进行排序

TreeSet 是 Set 接口的一个实现,它内部使用红黑树(Red-Black Tree)来维护元素的顺序。TreeSet 默认按照元素的自然顺序进行排序,也可以通过 Comparator 来指定自定义的排序顺序。以下是如何使用 TreeSet 进行排序的步骤:

创建 TreeSet 对象:

TreeSet<Integer> treeSet = new TreeSet<>();

添加元素:

treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
treeSet.add(1);  // 重复的元素不会被添加

使用自然顺序: 默认情况下,TreeSet 使用元素的自然顺序进行排序。如果元素没有实现 Comparable 接口,则不能使用 TreeSet。
使用自定义顺序: 如果你需要自定义排序顺序,可以提供一个 Comparator 对象。

treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
treeSet.add(1);

treeSet.add(5);
treeSet.add(2);

// 自然顺序
System.out.println(treeSet); // 输出: [1, 1, 2, 3, 4, 5]

// 自定义顺序
treeSet.add(3);
treeSet.add(1);
treeSet.add(4);
treeSet.add(1);

treeSet.add(5);
treeSet.add(2);

Comparator<Integer> comparator = new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2 - o1;  // 逆序排序
    }
};

treeSet.sort(comparator);
System.out.println(treeSet); // 输出: [5, 4, 3, 2, 1, 1]

获取集合的迭代器:

Iterator<Integer> iterator = treeSet.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

获取集合的大小:

int size = treeSet.size();
System.out.println("集合大小: " + size);

获取集合的第一个元素:

Integer firstElement = treeSet.first();
System.out.println("第一个元素: " + firstElement);

获取集合的最后一个元素:

Integer lastElement = treeSet.last();
System.out.println("最后一个元素: " + lastElement);

清空集合:

treeSet.clear();

判断集合是否为空:

boolean isEmpty = treeSet.isEmpty();
System.out.println("集合是否为空: " + isEmpty);

TreeSet 中的元素必须是可比较的,这意味着元素必须实现 Comparable 接口,或者你可以提供一个 Comparator 对象来指定自定义的比较规则。

标签:Set,元素,用法,add,set,哈希,集合,一些,treeSet
From: https://blog.csdn.net/m0_68933188/article/details/137270557

相关文章

  • 掌握Go语言:Go语言类型转换,解锁高级用法,轻松驾驭复杂数据结构(30)
    在Go语言中,类型转换不仅仅局限于简单的基本类型之间的转换,还可以涉及到自定义类型、接口类型、指针类型等的转换。以下是Go语言类型转换的高级用法详解:Go语言类型转换的高级用法1.自定义类型之间的转换在Go语言中,可以使用类型别名或自定义类型来创建新的数据类型。自定......
  • 一些乱七八糟的题单之类的
    打算每做一道题都放到这里,因为我之前的题单被我弃用然后删了QAQ知识点肯定不全。。。我啥时候写到对应知识点再加过去,对于一些很多做法题目按照我写的是啥为准(Link-CutTree链操作/维护链上信息P4847银河英雄传说V2P1501[国家集训队]TreeIIP4332[SHOI2014]三叉神经树......
  • PowerShell中调用GPU命令通常涉及到与GPU相关的任务,如查看GPU信息、管理GPU驱动、执行
    PowerShell中调用GPU命令通常涉及到与GPU相关的任务,如查看GPU信息、管理GPU驱动、执行GPU加速的计算任务等。以下是一些常见的PowerShell中调用GPU命令的示例:查看GPU信息:Get-WmiObject-Namespace"root\CIMV2"-ClassWin32_VideoController:通过WMI获取GPU信息,包括名称、制......
  • 【python】字典(Dictionary)与集合(Set)
    字典是一种键值对的数据结构,而集合是一种无序、元素不重复的数据结构。目录前言正文一、字典(dict)    1、字典的定义    注意:        2、字典的查询    2.1语法:字典名['键名']    2.2语法:字典名.get('键名')   ......
  • 3. dataset、dataloader
    dataset数据集dataloader数据加载器1.AI训练时的需求有一个数据集文件来,里面有100w的样本和标签训练时,通常希望,一次在100w中随机抓取batch个样本,拿去训练如果全部抓取完毕,则重新打乱后,再来一次2.dataset,数据集作用:储存数据集的信息self.xxx获取数据集长度__len_......
  • 关于过四级的一些神级技巧
    听力大家都知道,四级中所有的题,往往听力是最难的,但是同时这里就有一些听力仅供大家参考技巧一背听力高频词汇法   :众所周知,四级的词汇量其实不算太高,一般情况一下,在四级的阅读和翻译中,大家大部分的单词都可以记得;所以,我自己在这的意见是,大家尽可能的去认识四级中的高频词......
  • 记录一次使用unordered_set插入数据异常的问题
    问题描述问题和unordered_set有关,相关代码如下://打印unordered_set的所有值voidprintSet(conststd::unordered_set<std::string>&data){intindex=0;autoit=data.begin();for(;it!=data.end();++it){conststd::string&key=*i......
  • 掌握ADB:详解操作命令及完整用法指南(二)
    前言ADB,全名AndroidDebugBridge,是Android提供的一个通用的调试工具,是一个C/S架构的命令行工具,通过这个工具,使得我们的PC能够和Android设备来进行通信。之前一篇文章我们介绍了adb安装以及一些adb的基础命令,本文我们将介绍一些我们在进行app自动化测试时经常使用到的命令。adb......
  • guice的MethodInterceptor的用法和使用场景和设计思想
    Guice是一个轻量级的依赖注入框架,它也提供了AOP(面向切面编程)的功能,其中MethodInterceptor是Guice用来实现AOP的一个接口。MethodInterceptor的用法:MethodInterceptor接口是AOP联盟(AOPAlliance)的一部分,Guice使用这个接口来定义方法拦截器。拦截器可以在方法执行前后添加......
  • python golang 安装私有库的用法
    python安装在requirements.txt增加了github私有安装库的依赖git+https://${GITHUB_TOKEN}@github.com/YOLOTECHNOLOGY/bossjob-auth-lib.git@${GITHUB_LIB_BRANCH}当前该库无法通过pipenv直接安装,需要进入到虚拟环境,通过pipinstall进行安装安装前需要设置GITHUB_......