使用Java 8将列表转换为集合

4

最近我发现了Java 8的新语法,可以用来将列表转换为集合:

Set<Integer> myset = mylist.stream().collect(Collectors.toSet()));

我想了解使用这种方法将列表转换为集合的优势,与传统方法(通过将其作为参数传递给HashSet)相比。

6
如果你只是这样做的话,与 new HashSet(mylist) 相比没有任何优势。如果你想要过滤或映射你的流(stream),那么使用它就有优势。 - khelwood
请老老实实地使用旧方法。JDK的制造商已经优化了HashSet的构造函数,使其能够高效工作。使用stream()并不是很好的选择。 - Dawood ibn Kareem
因为HashSet的构造函数在插入元素之前将内部映射初始化为合理大小? - Michael
1
@Michael,这部分是因为创建流存在实际的、可测量的开销,另一部分是因为我们可以信任 Oracle 确保 HashSet 构造函数中发生的事情是“最佳可能的”。对我来说,一个很重要的因素是可读性。new HashSet(myList)myList.stream().collect(Collectors.toSet())更容易理解,无论函数式编程的传道者们对后者有多么兴奋。 - Dawood ibn Kareem
3个回答

11

优点在于这样可以更容易地(或者更准确地说,需要较少的语法改变)同时执行其他函数操作。

比如说以后你只想要集合中的偶数,你可以轻松地使用筛选器实现:

Set<Integer> myset = mylist.stream()
        .filter(p -> p%2==0)
        .collect(Collectors.toSet());

如果你按照传统的方式操作,那么你需要将其转换为上述语法,或编写额外的循环来提取所需的值。

(这并不意味着它总是更好-可能有一些情况下,您希望阻止将来的某个人更改代码以过滤值,在这种情况下,您可以认为传统的方式仍然比较可取。)


2
因此,仅仅使用Java 8将列表转换为集合并不能提高性能,我应该坚持使用传统的方式来实现相同的功能。 - Tushar Banne
1
@TusharBanne 正确(但您不应该根据微小的性能假设编写代码 - 坚持使用最易读的方式)。Java 8流API并不是为了这些类型的操作而设计成巨大的性能提升,它提供了编写更简洁、类似函数式的代码的能力。 - Michael Berry

1

您可以直接使用这段精确的代码:

Set<Integer> myset = new HashSet<>(mylist);

就是这样。


1
请查看下面使用Java 8的流API将List转换为Set的代码:
package streamapi;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
class Person{
    int empid;
    String name;
    
    Person(int empid,String name){
        this.empid = empid;
        this.name = name;
    }
    
    public String toString(){
        return "id"+this.empid+"name"+this.name;
    }
    
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        if(p.empid==this.empid && p.name.equals(this.name)) {
            return true;
        }
        return false;
    }
    
    public int hashCode() {
        return this.empid+this.name.hashCode();
    }
}

public class collectionFilter {

    public static void main(String[] args) {
        List<Person> list = new ArrayList();
        list.add(new Person(101,"aaa"));
        list.add(new Person(200,"bbbb"));
        list.add(new Person(150,"ccccc"));
        list.add(new Person(250,"ddddd"));
        list.add(new Person(250,"ddddd"));
        
        converListToSet(list);
    }
    
    public static void converListToSet(List<Person> list) {
        Set<Person> set = list.stream()
                .collect(Collectors.toSet());
        set.forEach(person->System.out.println(person));
    }
}

输出如下:
id200namebbbb
id101nameaaa
id150nameccccc
id250nameddddd

你可以看到上面的例子中,我们向ArrayList中添加了重复的Person对象,然后使用StreamAPI将其转换为列表,最终只获取了唯一值而没有重复项。请复制并运行此代码,我希望您能清楚地理解这个过程。 - Manas Kumar Maharana
1
缩写形式:set.forEach(System.out::println) - Mr. Polywhirl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接