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]