使用Streams合并2个列表的方法面临的问题。目前,当我使用Stream.concat时,它会添加到列表的底部,这不是我想要的。
的List1:
列表2:
理想合并输出:
如果上述情况不可行,那么下面也可以接受
我目前得到的输出,这不是我想要的
代码:
List<List<XSSFCell>> listData1 = list1.stream().skip(1).collect(Collectors.toList());
List<List<XSSFCell>> listData2 = list2.stream().skip(1).collect(Collectors.toList());
Stream stream = Stream.concat(listData1.stream(),listData2.stream());
希望我面临的问题很明确,等待指导。
加 此问题已标记为此question的副本但无法找到解决方案中提到的StreamUtils.zip方法。该问题的第一个答案是,各州自行承担风险。这可以使用标准的可用库来完成,还是我可以知道如何在StreamUtils中获得zip方法
答案 0 :(得分:0)
这一切都取决于你想要获得多么复杂,但长话短说,你必须每次都为你的第二个列表创建一个新的流,所以你不能给两个流 - - 您可以获得一个流(您采取行动)和Collection
/ List
,但不能获得两个流。这是因为如果没有抛出第二个流被关闭或运行的异常,你就不能stream1.forEach(stream2)
。
这是我的设置:
public static void main(String[] args) {
Collection<List<String>> list1 = new ArrayList<>(5);
Collection<List<String>> list2 = new ArrayList<>(5);
list1.add(Arrays.stream(new String[] {"ABC", "123", "456"}).collect(Collectors.toList()));
list1.add(Arrays.stream(new String[] {"DEF", "234", "567"}).collect(Collectors.toList()));
list1.add(Arrays.stream(new String[] {"GHI", "345", "678"}).collect(Collectors.toList()));
list2.add(Arrays.stream(new String[] {"ABC", "789", "012"}).collect(Collectors.toList()));
list2.add(Arrays.stream(new String[] {"DEF", "890", "123"}).collect(Collectors.toList()));
list2.add(Arrays.stream(new String[] {"GHI", "901", "234"}).collect(Collectors.toList()));
}
现在,根据您需要做多少检查以及知道两个流都有匹配键的条目(这里的地图确实比两个集合更好),以及你可以跳过很多错误检查,等等:
private static Stream<List<String>> combineTwoStreams(Collection<List<String>> list1,
Collection<List<String>> list2) {
Map<String, List<String>> newCollection = new LinkedHashMap<>();
list1.stream()
// Run through each entry in list1
.forEach(row -> {
// Find the entries in list2 that have the same 'key' and add them to newCollection
list2.stream().filter(row2 -> row.get(0).equals(row2.get(0))).forEach(row2 -> {
String key = row.get(0);
// Pull from newCollection
List<String> fromNewCollection = newCollection.get(key);
// If there wasn't an entry in newCollection for the key, add one now and pre-populate
// with list1's data
if (Objects.isNull(fromNewCollection)) {
fromNewCollection = new LinkedList<>(row);
newCollection.put(key, fromNewCollection);
}
// Add list2's data to the new collection (note that we can do an addAll instead
row2.subList(1, row2.size()).forEach(fromNewCollection::add);
});
});
// Return a Stream of our values
return newCollection.values().stream();
}
现在,如果你还要检查list2的东西,你可能想要这个:
private static Stream<List<String>> combineTwoStreams(Collection<List<String>> list1, Collection<List<String>> list2) {
Map<String, List<String>> newCollection = new LinkedHashMap<>();
list1.forEach(row -> newCollection.put(row.get(0), row));
list2.forEach(row -> {
String key = row.get(0);
// Pull from newCollection
List<String> fromNewCollection = newCollection.get(key);
// If there wasn't an entry in newCollection for the key, add one now and pre-populate
// with list1's data
if (Objects.isNull(fromNewCollection)) {
fromNewCollection = new LinkedList<>(row);
newCollection.put(key, fromNewCollection);
} else
// Add list2's data to the new collection (note that we can do an addAll instead
row.subList(1, row.size()).forEach(fromNewCollection::add);
});
// Return a Stream of our values
return newCollection.values().stream();
}
如果您想要防止重复,LinkedHashSet
很棒,那么您可能newCollection
为Map<String, Set<String>> newCollection = new LinkedHashMap<>();
,然后您只需LinkedHashSet
。
最后,如果你想让自己睁大眼睛:
private static Stream<List<Object>> combineTwoStreams(Collection<List<String>> list1, Collection<List<String>> list2) {
Map<String, List<String>> map1 = // Turn our first list into map map
list1.stream().collect(Collectors.toMap(row1 -> row1.get(0), row1 -> row1));
Map<String, List<String>> map2 = // Turn our second list into a map
list2.stream().collect(Collectors.toMap(row2 -> row2.get(0), row2 -> row2.subList(1, row2.size())));
return Stream
.of(map1, map2)
// Give me the EntrySets as a stream
.flatMap(m -> m.entrySet().stream())
// Collect it all down
.collect(
// Group together things by the "key" so that we have a Map<String,List<List<String>>>
Collectors.groupingBy(
Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
// Merge the lists within each list down so that we have
// Map<String,List<String>>
Collectors.collectingAndThen(
Collectors.toList(),
row -> row.stream().flatMap(Collection::stream)
.collect(Collectors.toList())))))
// Get the values from our Map
.values()
// Return the stream of List<String>
.stream();
}