Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在创建子列表的特定值之间进行筛选_Java_List_Java Stream - Fatal编程技术网

Java 在创建子列表的特定值之间进行筛选

Java 在创建子列表的特定值之间进行筛选,java,list,java-stream,Java,List,Java Stream,我有以下清单: List<String> names= Arrays.asList(new String[]{"Tom", "louis", "martha", "Tom", "john", "Carol", "Tom", "Simon"}); 我用传统的方法处理索引 我的方式是公正的 List<Integer>

我有以下清单:

List<String> names= Arrays.asList(new String[]{"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]
}
List positionsWithTom=new ArrayList();

对于(int i=0;i首先,我收集了元素(
[0,3,6]
)的索引,这些元素的值
“Tom”
tomindex
列表中。然后我使用了方法

本部分:

j == tomindex.size() - 1 ? names.subList(tomindex.get(j), names.size())
                        : names.subList(tomindex.get(j), tomindex.get(j + 1))
不要错过最后一个元素。
tomindex
的最后一个元素是
6
,我们需要获取索引
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);

我不相信这很容易适用于流。流方法在表达问题陈述时也不会比简单的循环更清晰

只要您不关心子列表的顺序,使用
List.lastIndexOf
while循环
就非常简单了。请注意,由于这会破坏原始列表,而且这些子列表不重叠,因此子列表不可能因对原始列表的更改或每个ot而更改她(除非存在对原始文件的引用)。但是,如果有问题,可以将
子列表作为参数传递给
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);

请注意,可以通过在
add
方法中指定索引
0
来颠倒顺序。但是,由于复制的原因,
ArrayLists
的成本可能会很高。
LinkedList
会减轻这一开销,但会带来一些开销

这是我的流解决方案,仅供补充。

  • 首先,根据
    Tom
    所在的位置,在连续的
    子列表中对名称进行流式处理。因此,第一个列表包含所有名称,第二个列表包含除最后一个
    “Tom”
    分组以外的所有名称,依此类推
  • 然后,对于这些子列表中的每一个子列表,从末尾选择以
    Tom
    开头的最后一个子列表
  • 并将列表放入一个集合中

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

我手头没有Java流API语法解决方案,但你的直觉是正确的:原则上,这可以通过流优雅地完成。首先,你需要计算
“Tom”
元素;对于您的示例,这将为您提供序列1、1、1、2、2、2、3、3。您可以将这些数字用作
groupingBy
收集器的类。(这些都可以在一次传递中完成。)我发布了流式和非流式解决方案。我更喜欢后者。
[[Tom, louis, martha], [Tom, john, Carol], [Tom, Simon]]
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]
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]