获取列表中最后一次出现的特定字符串

时间:2019-02-10 14:30:38

标签: java string list

我有一个简单的字符串列表。我的目标是按组获取列表中每个字符串的最新出现。

这是模式代码:

 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”。

该怎么做?

5 个答案:

答案 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,所以从最后移到第一,而不是从最后移到最后。这将使管理更加轻松,并使代码更简洁。
  • 使用substring()方法获取字符串所属的组。
  • 使用set跟踪已访问的组。
  • 如果该组中没有一个组,请将其添加到该组中,并将当前字符串添加到该组的答案中(因为这将是最后一次出现)。
  • 最后,返回列表。

答案 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放弃键(AB),而只获取原始字符串。

答案 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)

使用临时MapList 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));