我有一个简单的字符串列表。我的目标是按组获取列表中每个字符串的最新出现。
这是模式代码:
List<String> newData = new ArrayList<>();
newData.add("A-something");
newData.add("A-fdfdsfds");
newData.add("A-fdsfdsfgs");
newData.add("B-something");
newData.add("B-dsafdrsafd");
newData.add("B-dsdfsad");
我希望仅获取每个组的最后一次出现。换句话说,我只想获得“ A-fdsfdsfgs”和“ B-dsdfsad”。
该怎么做?
答案 0 :(得分:2)
要获得每个组的最后一次出现,可以将stream api与groupingBy一起使用:
import static java.util.stream.Collectors.*;
Map<String, Optional<String>> collect = newData.stream()
.collect(groupingBy(strings -> strings.split("-")[0],
mapping(s -> s, maxBy(Comparator.comparingInt(newData::lastIndexOf)))));
注意:地图的值为Optional
要在没有Optional
的情况下使用它,请使用toMap
而不是groupingBy
:
Map<String, String> collect = newData.stream()
.collect(toMap(s -> s.split("-")[0],
Function.identity(),
(s1, s2) -> newData.lastIndexOf(s1) > newData.lastIndexOf(s2) ? s1 : s2));
此外,如果您想获取不带组名的地图值,则将Function.identity()
更改为s -> s.split("-")[1]
答案 1 :(得分:1)
import java.util.*;
class Solution {
public static void main(String[] args) {
List<String> newData = new ArrayList<>();
newData.add("A-something");
newData.add("A-fdfdsfds");
newData.add("A-fdsfdsfgs");
newData.add("B-something");
newData.add("B-dsafdrsafd");
newData.add("B-dsdfsad");
System.out.println(lastOccurrences(newData).toString());
}
private static List<String> lastOccurrences(List<String> data){
Set<String> set = new HashSet<>();
List<String> ans = new ArrayList<>();
for(int i=data.size()-1;i>=0;--i){
String group = data.get(i).substring(0,data.get(i).indexOf("-"));
if(set.contains(group)) continue;
set.add(group);
ans.add(data.get(i));
}
return ans;
}
}
输出:
[B-dsdfsad, A-fdsfdsfgs]
算法:
last occurrences
,所以从最后移到第一,而不是从最后移到最后。这将使管理更加轻松,并使代码更简洁。答案 2 :(得分:1)
有几种方法可以做到,其他答案已经显示出来。我会发现类似以下内容的东西:
Collection<String> lastOfEach = newData.stream()
.collect(Collectors.groupingBy((String s) -> s.split("-")[0],
Collectors.reducing("", s -> s, (l, r) -> r)))
.values();
lastOfEach.forEach(System.out::println);
在您的列表中,输出为:
A-fdsfdsfgs
B-dsdfsad
我的分组与其他几个答案相同。在分组的值上,我每次要减少两个字符串时,都要进行归约。最后,这将根据要求提供每个组的最后一个字符串。由于groupingBy
会生成一个映射,因此我使用values
放弃键(A
和B
),而只获取原始字符串。
答案 3 :(得分:0)
通过分组进行收集就足够了。
final Map<String, List<String>> grouped =
newData.stream()
.collect(groupingBy(s -> s.split("-")[0]));
final List<String> lastOccurrences =
grouped.values()
.stream()
.filter(s -> !s.isEmpty())
.map(s -> s.get(s.size() - 1))
.collect(toList());
对于Java 11,filter
变为filter(not(List::isEmpty))
这会给你fdsfdsfgs, dsdfsad
答案 4 :(得分:0)
使用临时Map
。 List
finalList 仅具有必需的值
Map<String, String> tempMap = new HashMap<>();
List<String> finalList = new ArrayList<>();
newData.forEach((val) -> tempMap.put(val.split("-")[0], val.split("-")[1]));
tempMap.forEach((key, val) -> finalList.add(key + "-" + val));