【问题标题】:How to compare 2 lists using Stream and get element form compare list?如何使用 Stream 比较 2 个列表并获取元素形式比较列表?
【发布时间】:2020-03-18 07:58:35
【问题描述】:
//FullName(String name, String fullName)
List<FullName> fullNameList = Arrays.asList(
            new FullName("Alpha", "Alpha Maz"),
            new FullName("Beta", "Beta Sew"),
            new FullName("Delta", "Delta Non"),
            new FullName("Indigo", "Indigo Loe")
            );

List<String> nameList = Arrays.asList(new String[] {"Delta","Alpha"});

让我们以上面的示例列表为例。 我想将 nameList 与 fullNameList 进行比较,如果找到任何匹配项,则返回全名。

我必须使用 nameList 作为主要,因为我希望结果遵循 nameList 中的序列,我不知道如何从比较列表 (fullNameList) 中“收集”元素

String result= nameList.stream()
            .filter(v -> fullNameList.stream().anyMatch(s -> s.getName().equals(v)))
            .collect(Collectors.joining(","));

Actual Result : "Delta,Alpha"
Expected Result : "Delta Non,Alpha Maz"

知道如何使用 Java 8 Stream 做到这一点吗?

【问题讨论】:

  • 澄清 - 如果 namesList 中的名字与 fullName 列表中的名字匹配,您想将完整名称提取到另一个列表中吗?
  • 是的,这就是我想要的结果。
  • 如果输出的顺序无关紧要,您可以将名称存储为Set,然后在遍历fullNameList 时,过滤相关名称并映射以进一步执行连接。

标签: java java-stream


【解决方案1】:
Map<String, String> nameMapper = fullNameList.stream()
                    .collect(Collectors.toMap(FullName::getFirstName, FullName::getFullName));

List<String> filteredList = nameList.stream()
                            .filter(nameMapper::containsKey)
                            .map(nameMapper::get)
                            .collect(Collectors.toList());

System.out.println("nameList = " + nameList);
System.out.println("filteredList = " + filteredList);

nameList = [靛蓝,阿尔法,德尔塔] filtersList = [Indigo Loe, Alpha Maz, Delta Non]

nameList = [Delta, Alpha] filtersList = [Delta Non, Alpha Maz]

虽然创建 Map 会产生开销,但对于实时应用程序,如果列表的数量很大,则迭代成本会更低,因为提取是 O(1),因为 String 本身不太可能创建哈希碰撞。在这种情况下,您的获取也是 O(log n)。

如果列表较小,我认为Eran的答案更合适。

【讨论】:

  • 根据我的理解,与在nameList 中为每个name 处理多次fullNameList 相比,没有理由对已处理的内存中列表的成本很高。只是你可以修改它以使用Collectors.joining 来匹配 OP 的要求。
  • 是的,你可以根据你的要求更改减量
【解决方案2】:

您需要使用map 而不是filter 才能将短名称映射到相应的全名。

String result= 
    nameList.stream()
            .map(v -> fullNameList.stream()
                                  .filter(s -> s.getName().equals(v))
                                  .findFirst()
                                  .map(FullName::getFullName))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collectors.joining(","));

这是假设FullName 类有一个getFullName() 方法可以返回您希望收集的数据。

【讨论】:

    【解决方案3】:

    只需对代码稍作改动,即可获得预期的输出。

    String res = fullNameList.stream().filter(f -> nameList.stream().anyMatch(n -> n.equals(f.getName()))).map(f -> f.getfullName()).collect(Collectors.joining(",")); 
    

    输出:Alpha Maz,Delta Non

    【讨论】:

    • I have to use nameList as primary as I want the result to be following the sequence in nameList
    【解决方案4】:

    如果您将nameList 限制为主要,那么您可以使用以下内容:

    String result = nameList.stream()
                    .flatMap(name -> fullNameList.stream()
                            .filter(fullName -> fullName.getName().equals(name))
                            .map(FullName::getFullName)
                    )
                    .collect(Collectors.joining(","));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 2022-06-26
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多