繁体   English   中英

如何根据 Java 中另一个列表中的项目从列表的子集中获取项目列表?

[英]How do I get a list of items from a subset of a list, based on the items in another list in Java?

我有一个List<String> ,它代表另一个列表中项目的 ID(可以是重复的),它是一个List<Cheat> ,其中每个 Cheat 都有一个 String ID 和一个List<Integer> RNG 两者在 Cheat 中都有访问器方法。

我需要将这个 ID 列表转换为一个 RNG 列表,用于为我提供 ID 的每个作弊。

例如,我可以有 3 个秘籍:

1:{ID:1, RNG:{1,2,3}}
2:{ID:2, RNG{1,2}}
3:{ID:3, RNG:{1}}

以及以下 ID 的列表:

{3,1,1,2}.

我需要最终得到 {1,1,2,3,1,2,3,1,2} 的最终列表,这是作弊 3 的 RNG,然后是作弊 1 的 RNG,然后是作弊 1 的 RNG再次作弊 1,最后是作弊 2 的 RNG。

如果有人可以帮助我,将不胜感激。 谢谢你。

我尝试过但失败了:

ImmutableList<Integer> sequenceRngs = cheatIds.stream()
                                              .map(s -> cheats.stream()
                                                                .filter(cheat -> cheat.getId().equals(s))
                                                                .findFirst()
                                                                .map(cheat -> cheat.getRng()))
                                              .flatMap(cheat -> cheat.getRng())
                                              .collect(ListUtils.toImmutableList());

一种可能的解决方案:

import java.util.List;
import java.util.stream.Collectors;

class Scratch {

    static class Cheat {
        int id;
        List<Integer> rng;

        public Cheat(int id, List<Integer> rng) {
            this.id = id;
            this.rng = rng;
        }
    }

    public static void main(String[] args) {

        List<Cheat> allCheats = List.of(
                new Cheat(1, List.of(1,2,3)),
                new Cheat(2, List.of(1,2)),
                new Cheat(3, List.of(1))
        );

        List<Integer> result = List.of(3, 1, 1, 2).stream()
                .flatMap(id -> allCheats.stream()
                        .filter(cheat -> cheat.id == id)
                        .findFirst().orElseThrow().rng.stream())
                .collect(Collectors.toList());

        System.out.println(result);

    }
}

关键是使用 flatMap 最终将结果放在单个而不是嵌套的 Collection 中。

您传递给flatMap的 lambda 应该返回一个Stream ,而不是一个List 并且您应该处理流中没有此类元素的情况 - 即使您确定存在。 这样的事情应该做:

final ImmutableList<String> sequenceRngs = cheatIds.stream().flatMap(id ->
    cheats.stream().filter(cheat -> id.equals(cheat.getId()))
        .findAny().orElseThrow(IllegalStateException::new)
        .getRng().stream())
    .collect(ListUtils.toImmutableList());

另外,我建议将作弊列表转换为地图 - 这将简化代码并降低从 O(n) 到 O(1) 的搜索复杂性。

您可以通过以下步骤实现:

  1. 创建cheatId到RNG id关联的映射:

     Map<Integer, List<Integer>> map = cheats.stream() .collect(Collectors.toMap(Cheat::getId, cheat -> cheat.getRng().stream().map(RNG::getId).collect(Collectors.toList())));
  2. 迭代作为输入提供的cheatIds ,并从地图中获取相应的RNG id以作为输出收集:

     List<Integer> output = cheatIds.stream() .flatMap(ch -> map.get(ch).stream()) .collect(Collectors.toList());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM