【问题标题】:Easiest way to convert a List to a Set in Java在 Java 中将 List 转换为 Set 的最简单方法
【发布时间】:2010-11-28 15:04:54
【问题描述】:

在 Java 中将 List 转换为 Set 的最简单方法是什么?

【问题讨论】:

    标签: java collections


    【解决方案1】:

    在 Java 1.8 中,流 API 可用于将列表转换为集合。例如,下面的代码展示了列表到集合的转换:

    List<String> empList = Arrays.asList("java", "python", ".net", "javaScript", "php");
    Set<String> set = empList.stream().collect(Collectors.toSet());
    set.forEach(value -> System.out.printf("%s ", value));
    

    如果列表包含对象并且我想从中创建一个集合:

    List<Employee> empList = Arrays.asList(new Employee(1, 1000, "Chandra Shekhar", 6000),
    new Employee(2, 1000, "Rajesh", 8000), new Employee(3, 1004, "Rahul", 9000),
    new Employee(4, 1001, "Suresh", 12000), new Employee(5, 1004, "Satosh", 7000));
    
    Set<String> set = empList.stream().map(emp -> emp.getName()).collect(Collectors.toSet());
    System.out.println(set);        
    

    【讨论】:

      【解决方案2】:

      请记住,从 List 转换为 Set 将从集合中删除重复项,因为 List 支持重复项,但 Set 不支持 Java 中的重复项。

      直接转换:将 List 转换为 Set 的最常见和最简单的方法

      // Creating a list of strings
      List<String> list = Arrays.asList("One", "Two", "Three", "Four");
      
      // Converting a list to set
      Set<String> set = new HashSet<>(list);
      

      Apache Commons Collections:您也可以使用 Commons Collections API 将 List 转换为 Set:-

      // Creating a list of strings
      List<String> list = Arrays.asList("One", "Two", "Three", "Four");
      
      // Creating a set with the same number of members in the list 
      Set<String> set = new HashSet<>(4);
      
      // Adds all of the elements in the list to the target set
      CollectionUtils.addAll(set, list);
      

      使用 Stream: 另一种方法是将给定列表转换为流,然后将流转换为集合:-

      // Creating a list of strings 
      List<String> list = Arrays.asList("One", "Two", "Three", "Four"); 
      
      // Converting to set using stream 
      Set<String> set = list.stream().collect(Collectors.toSet()); 
      

      【讨论】:

        【解决方案3】:

        Java- addAll

        set.addAll(aList);
        

        Java- 新对象

        new HashSet(list)
        

        Java-8

        list.stream().collect(Collectors.toSet());
        

        使用番石榴

         Sets.newHashSet(list)
        

        Apache Commons

        CollectionUtils.addAll(targetSet, sourceList);
        

        Java 10

        var set = Set.copyOf(list);
        

        【讨论】:

        • 它们之间有性能差异吗?
        • 我认为这个答案应该被标记为最佳答案。谢谢!
        【解决方案4】:

        如果你使用Eclipse Collections

        MutableSet<Integer> mSet = Lists.mutable.with(1, 2, 3).toSet();
        MutableIntSet mIntSet = IntLists.mutable.with(1, 2, 3).toSet();
        

        MutableSet 接口扩展了java.util.Set,而MutableIntSet 接口没有。您还可以使用 Sets 工厂类将任何 Iterable 转换为 Set

        Set<Integer> set = Sets.mutable.withAll(List.of(1, 2, 3));
        

        在 Eclipse Collections here 中有更多关于可变工厂的解释。

        如果你想从List 得到一个ImmutableSet,你可以使用Sets 工厂,如下所示:

        ImmutableSet<Integer> immutableSet = Sets.immutable.withAll(List.of(1, 2, 3))
        

        注意:我是 Eclipse Collections 的提交者

        【讨论】:

          【解决方案5】:

          构造函数的最佳使用方式

          Set s= new HashSet(list);
          

          在 java 8 中你也可以使用流 api::

          Set s= list.stream().collect(Collectors.toSet());
          

          【讨论】:

            【解决方案6】:

            对于 Java 8,这非常简单:

            List < UserEntity > vList= new ArrayList<>(); 
            vList= service(...);
            Set<UserEntity> vSet= vList.stream().collect(Collectors.toSet());
            

            【讨论】:

            • "Real" Java 8 将使用new ArrayList&lt;&gt;() ;-)
            【解决方案7】:

            使用 Java 10,您现在可以使用 Set#copyOf 轻松地将 List&lt;E&gt; 转换为不可修改的 Set&lt;E&gt;

            例子:

            var set = Set.copyOf(list);
            

            请记住,这是一个无序操作,null 元素是不允许允许的,因为它会抛出 NullPointerException

            如果您希望它是可修改的,那么只需将其传递给构造函数 Set 实现即可。

            【讨论】:

              【解决方案8】:

              Optional.ofNullable 的 Java 8 弹性解决方案

              Set<Foo> mySet = Optional.ofNullable(myList).map(HashSet::new).orElse(null);
              

              【讨论】:

                【解决方案9】:

                我们不要忘记我们相对较新的朋友 流 API。 如果您需要在将列表转换为集合之前对其进行预处理,最好使用以下内容:

                list.stream().<here goes some preprocessing>.collect(Collectors.toSet());
                

                【讨论】:

                  【解决方案10】:

                  我同意 sepp2k,但还有一些其他细节可能很重要:

                  new HashSet<Foo>(myList);
                  

                  会给你一个没有重复的未排序集合。在这种情况下,使用对象上的 .equals() 方法来识别重复。这是结合 .hashCode() 方法完成的。 (更多关于平等的信息请看here

                  给出排序集的另一种方法是:

                  new TreeSet<Foo>(myList);
                  

                  如果 Foo 实现了 Comparable,这将有效。如果没有,那么您可能需要使用比较器:

                  Set<Foo> lSet = new TreeSet<Foo>(someComparator);
                  lSet.addAll(myList);
                  

                  这取决于 compareTo()(来自可比较接口)或 compare()(来自比较器)以确保唯一性。因此,如果您只关心唯一性,请使用 HashSet。如果您在排序之后,请考虑 TreeSet。 (记住:稍后优化!)如果时间效率很重要,如果空间效率很重要,请使用 HashSet,看看 TreeSet。请注意,通过 Trove(和其他位置)可以获得更有效的 Set 和 Map 实现。

                  【讨论】:

                  • 感谢您提供自定义比较器用例!
                  【解决方案11】:

                  有多种方法可以获得Set

                      List<Integer> sourceList = new ArrayList();
                      sourceList.add(1);
                      sourceList.add(2);
                      sourceList.add(3);
                      sourceList.add(4);
                  
                      // Using Core Java
                      Set<Integer> set1 = new HashSet<>(sourceList);  //needs null-check if sourceList can be null.
                  
                      // Java 8
                      Set<Integer> set2 = sourceList.stream().collect(Collectors.toSet());
                      Set<Integer> set3 = sourceList.stream().collect(Collectors.toCollection(HashSet::new));
                  
                      //Guava
                      Set<Integer> set4 = Sets.newHashSet(sourceList);
                  
                      // Apache commons
                      Set<Integer> set5 = new HashSet<>(4);
                      CollectionUtils.addAll(set5, sourceList);
                  

                  当我们使用Collectors.toSet() 时,它会返回一个集合,并且根据文档:There are no guarantees on the type, mutability, serializability, or thread-safety of the Set returned。如果我们想得到一个HashSet,那么我们可以使用另一种方法来得到一个集合(检查set3)。

                  【讨论】:

                    【解决方案12】:

                    您可以将List&lt;&gt; 转换为Set&lt;&gt;

                    Set<T> set=new HashSet<T>();
                    
                    //Added dependency -> If list is null then it will throw NullPointerExcetion.
                    
                    Set<T> set;
                    if(list != null){
                        set = new HashSet<T>(list);
                    }
                    

                    【讨论】:

                    • 我想你的意思是把它从 List 转换到 Set。
                    【解决方案13】:
                    Set<E> alphaSet  = new HashSet<E>(<your List>);
                    

                    或完整的例子

                    import java.util.ArrayList;
                    import java.util.HashSet;
                    import java.util.List;
                    import java.util.Set;
                    
                    public class ListToSet
                    {
                        public static void main(String[] args)
                        {
                            List<String> alphaList = new ArrayList<String>();
                            alphaList.add("A");
                            alphaList.add("B");
                            alphaList.add("C");
                            alphaList.add("A");
                            alphaList.add("B");
                            System.out.println("List values .....");
                            for (String alpha : alphaList)
                            {
                                System.out.println(alpha);
                            }
                            Set<String> alphaSet = new HashSet<String>(alphaList);
                            System.out.println("\nSet values .....");
                            for (String alpha : alphaSet)
                            {
                                System.out.println(alpha);
                            }
                        }
                    }
                    

                    【讨论】:

                    • +1 获取完整的代码示例。这里还有一点需要注意的是,不能保证每次运行的哈希值都是相同的。这意味着在“设置值.....”之后打印的列表可能是“ABC”一次运行和“CBA”另一次运行。正如我在回答中提到的,您可以使用树集来获得稳定的排序。另一种选择是使用 LinkedHashSet 来记住项目添加到其中的顺序。
                    【解决方案14】:
                    Set<Foo> foo = new HashSet<Foo>(myList);
                    

                    【讨论】:

                    • 虽然正确,但此答案缺乏足够的技术背景来保证成为最佳/可接受的答案,因为这里存在陷阱,具体取决于 SetMap 的哪个实现使用; HashSet 在此处假定
                    • @Madbreaks 专门针对这个问题来到这里,并建议使用 Ramesh 的解决方案和 Abdul 对任何有兴趣尝试这样做的人的解释
                    【解决方案15】:

                    使用 java 8 你可以使用流:

                    List<Integer> mylist = Arrays.asList(100, 101, 102);
                    Set<Integer> myset = mylist.stream().collect(Collectors.toSet()));
                    

                    【讨论】:

                    • 你检查过这方面的性能损失吗?这将执行一个 iterable+iterator、一个新的 HashSet(),然后对于每个列表项,在新集合上调用一个 addAll()。总的来说,cca。为像 new HashSet(list) 这样简单的东西创建了 5 个对象。
                    • @AgostonHorvath 感谢您的评论。我最初来这里时正在寻找那些信息。
                    【解决方案16】:

                    我会在转换为 set 之前执行 Null 检查。

                    if(myList != null){
                    Set<Foo> foo = new HashSet<Foo>(myList);
                    }
                    

                    【讨论】:

                    • Set&lt;Foo&gt; foo = myList == null ? Collections.emptySet() : new HashSet&lt;Foo&gt;(myList);
                    【解决方案17】:

                    如果您使用Guava 库:

                    Set<Foo> set = Sets.newHashSet(list);
                    

                    或者,更好:

                    Set<Foo> set = ImmutableSet.copyOf(list);
                    

                    【讨论】:

                    • 为什么 ImmutableSet.copyOf 更好?
                    • Guava 的 newHashSet() 比基本的 java new HashSet() 有什么优势?
                    • @Nelda.techspiress javadoc 讨论了何时应该或不应该使用该方法。注意最后一部分:这种方法不是很有用,将来可能会被弃用。虽然我有点惊讶没有提到一致性作为一个因素,就像ImmutableSet.of()一样,例如。编辑:这可能不是因素,因为 all 不需要重载。
                    • 嘿,感谢@shmosel 的参考,但我正在寻找更多的经验知识。用过 Guava 的人,为什么会选择 Guava 而不是 HashSet?
                    猜你喜欢
                    • 2011-01-20
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-08-14
                    • 2021-10-15
                    • 2014-10-27
                    • 2011-05-24
                    • 1970-01-01
                    相关资源
                    最近更新 更多