将流转换为LinkedHashSet

39
我想将.csv文件以自然顺序保存到LinkedHashSet中,所以.csv文件的第一行应该是LinkedHashSet的第一个元素。
文件看起来像这样:
java  
c  
c++  
assembly language  
swift  

我的代码看起来像这样:

public class test {   
    public static void main(String[] args) throws IOException {         
         final Charset ENCODING = Charset.forName("Cp1250");
         Path fileToLoad = Paths.get("src/main/resources/test.csv");
         Set<String> x = Files.lines(fileToLoad, ENCODING)
                 .map(Function.identity())
                 .collect(Collectors.toSet());

         Iterator<String> it = x.iterator();
         while(it.hasNext()) {
             System.out.println(it.next());
         }
    }
}

但是它返回的顺序不正确:

assembly language
c++
java
c
swift

我认为那个流应该保存为HashSet。

使用流能否将其保存为LinkedHashSet?


12
这是因为Collectors.toSet()不会使用LinkedHashSet而只会使用HashSet。可以尝试改用Collectors.toCollection( LinkedHashSet::new ) - Thomas
1
你似乎在寻找一个有序的List结构,而不是一个无序的Set - Dragonthoughts
1
从javadoc 这是一个未排序的Collector https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toSet-- - Jens
4个回答

92

你根本不知道那个工厂方法创建的具体类型(它保证只返回Set,没有其他)。

唯一可靠的方法是通过使用流操作结束控制实际发生的情况。

... collect( Collectors.toCollection( LinkedHashSet::new ) );

哦,我很蠢。谢谢。 - mondjunge
1
@mondjunge 当然不是。这似乎很明显,但我记得当我第一次读到这个问题时也曾被绊倒过。 - GhostCat

3

.collect(Collectors.toSet())并不会创建LinkedHashSet,而是创建一个普通的HashSet。建议使用.collect(Collectors.toCollection(LinkedHashSet::new)来确保使用LinkedHashSet


1

2
请注意,OP 表示他想使用 LinkedHashSet,它会按照插入顺序迭代元素。因此,在这里使用 set 和 iterator 是可以的,他只需要使用正确的实现即可。 - Thomas
@Thomas,你说得对,这种方法解决了问题,但与OP所问的方式不同。 - Ahorn

0

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