java—在特定值之间进行过滤,创建子列表

wd2eg0qa  于 2021-06-26  发布在  Java
关注(0)|答案(2)|浏览(259)

我有这个清单:

List<String> names= Arrays.asList(new String[]{"Tom", "louis", "martha", "Tom", "john", "Carol", "Tom", "Simon"});

我想创建三个不同的列表,将值放在单词之间:

"Tom", "louis", "martha";
"Tom", "john", "Carol";
"Tom", "Simon"

我用传统的方法处理索引
我的方式是公正的;

List<Integer> positionsWithTom = new ArrayList<>();

for(int i=0; i<names.size; i++){
...
positionsWithTom = [0,3,6]
}

然后将值放在不同的列表中
这样做并没有多大的好处,也许是流过滤?

2eafrhcq

2eafrhcq1#

首先我收集了元素的索引( [0, 3, 6] )有价值的 "Tom"tomindex 列表。然后我使用sublist()方法。
本部分:

j == tomindex.size() - 1 ? names.subList(tomindex.get(j), names.size())
                        : names.subList(tomindex.get(j), tomindex.get(j + 1))

就是不要错过最后一个。的最后一个元素 tomindex6 我们需要在索引之间获取值 6 以及 8 所以我们用 names.size() 最后。
试试这个:

List<Integer> tomindex = IntStream.range(0, names.size()).filter(i -> names.get(i).equals("Tom")).boxed()
        .collect(Collectors.toList());

Collection<List<String>> subLists = IntStream.range(0, tomindex.size())
        .mapToObj(j -> j == tomindex.size() - 1 ? names.subList(tomindex.get(j), names.size())
                : names.subList(tomindex.get(j), tomindex.get(j + 1)))
        .collect(Collectors.toList());

System.out.println(subLists);

输出:

[[Tom, louis, martha], [Tom, john, Carol], [Tom, Simon]]
3hvapo4f

3hvapo4f2#

我不相信这很容易使自己流。流方法在表达问题语句时也不会比简单的循环更清楚。
只要您不关心子列表的顺序,使用 List.lastIndexOf 和一个 while loop . 请注意,由于这会破坏原始列表,而且这些子列表不会重叠,因此子列表不可能因对原始列表的更改或相互更改而更改(除非存在对原始列表的引用)。但总有人能通过考试 sublist 作为 ArrayList 如果这是一个问题。

List<String> names = new ArrayList<>(List.of("Tom", "louis",
        "martha", "Tom", "john", "Carol", "Tom", "Simon"));

List<List<String>> lists = new ArrayList<>();

int start;
while ((start = names.lastIndexOf("Tom")) >= 0) {
    ists.add(names.subList(start, names.size()));
    names = names.subList(0, start);
}

lists.forEach(System.out::println);

印刷品

[Tom, Simon]
[Tom, john, Carol]
[Tom, louis, martha]

请注意,可以通过指定 0add 方法。但这对我来说可能很昂贵 ArrayLists 因为复制。一 LinkedList 会减少一点开销。
最后,这里是我的流解决方案。
首先,将名字连续地流式处理 sublists 根据地点 Tom 位于。所以第一个列表包含了所有的名字,第二个,除了最后一个 "Tom" 分组等等。
然后,对于每个子列表,从 Tom 从最后开始。
把这些清单收集起来。

List<List<String>> result = Stream.iterate(
            names,
            n -> n.size() > 0 && n.lastIndexOf("Tom") >= 0,
            n -> n.subList(0, n.lastIndexOf("Tom")))
        .map(n -> n.subList(n.lastIndexOf("Tom"), n.size()))
        .collect(Collectors.toList());

result.forEach(System.out::println);

印刷品

[Tom, Simon]
[Tom, john, Carol]
[Tom, louis, martha]

我仍然喜欢while循环解决方案,因为我认为它更干净、更简洁。更精通流的人可能会做得更好。

相关问题