简体   繁体   English

检查forEach lambda循环Java 8中List的范围

[英]Checking range of List in forEach lambda loop Java 8

I want to learn how I can check the range of a list in java 8. 我想学习如何检查java 8中列表的范围。

For example, 例如,

My Code: 我的代码:

    List<String> objList = new ArrayList<>();
    objList.add("Peter");
    objList.add("James");
    objList.add("Bart");

    objList.stream().map((s) -> s + ",").forEach(System.out::print);

My out come is 我出来了

    Peter,James,Bart,

but I want to know how I can get rid of the last , 但我想知道如何摆脱最后的,

Note: I know I must use filter here , yet I do not know how and I know there is another way to solve this which is as follows 注意:我知道我必须在这里使用过滤器,但我不知道如何以及我知道还有另一种方法可以解决这个问题,如下所示

String result = objList.stream()
    .map(Person::getFirstName)
    .collect(Collectors.joining(","));

yet I want to know how to check the range and get rid of , in my first code. 但我想知道如何检查范围并摆脱我的第一个代码。

You could do this: 你可以这样做:

objList.stream().flatMap((s) -> Stream.of(s, ','))
        .limit(objList.size() * 2 - 1).forEach(System.out::print);

flatMap replaces each element of the original stream with the elements in the streams returned from the mapping function. flatMap使用映射函数返回的流中的元素替换原始流的每个元素。

So if your stream was originally 所以如果你的流是最初的

"Peter" - "James" - "Bart"

The above mapping function changes it to 上面的映射函数将其更改为

"Peter" - "," - "James" - "," - "Bart" - ","

Then the limit removes the last "," by shortening the stream to be at most the length of the value that is passed to it, which in this case is the size of the stream - 1. The size of the stream was 2 * the size of the list before limit because flatMap doubled it's length. 然后, limit删除最后一个","通过将流缩短为最多传递给它的值的长度,在这种情况下是流的大小 - 1.流的大小是2 * limit之前的列表大小,因为flatMap加倍了它的长度。

Note that this will throw an IllegalArgumentException if the list is empty, because the value passed to limit will be -1. 请注意,如果列表为空,这将抛出IllegalArgumentException ,因为传递给limit的值将为-1。 You should check for this first if that is a possibility. 如果可能的话,你应该先检查一下。

There's no direct way to get the index of a stream item while you're processing the items themselves. 当您自己处理项目时,没有直接的方法来获取流项目的索引。 There are several alternatives, though. 但是,有几种选择。

One way is to run the stream over the indexes and then get the elements from the list. 一种方法是在索引上运行流,然后从列表中获取元素。 For each element index it maps i to the i'th element and appends a "," for all indexes except the last: 对于每个元素索引,它将i映射到第i个元素,并为除最后一个之外的所有索引附加“,”:

IntStream.range(0, objList.size())
    .mapToObj(i -> objList.get(i) + (i < objList.size()-1 ? "," : ""))
    .forEach(System.out::print);

A second, more concise variation is to special case the first element instead of the last one: 第二个更简洁的变化是特殊情况下的第一个元素而不是最后一个元素:

IntStream.range(0, objList.size())
    .mapToObj(i -> (i > 0 ? "," : "") + objList.get(i))
    .forEach(System.out::print);

A third way is to use the particular reduce operation that is applied "between" each two adjacent elements. 第三种方式是使用在每两个相邻元素“之间”应用的特定reduce操作。 The problem with this technique is that it does O(n^2) copying, which will become quite slow for large streams. 这种技术的问题在于它进行O(n ^ 2)复制,对于大流来说这将变得非常慢。

System.out.println(objList.stream().reduce((a,b) -> a + "," + b).get());

A fourth way is to special-case the last element by limiting the stream to length n-1. 第四种方法是通过将流限制为长度n-1来特殊情况下最后一个元素。 This requires a separate print statement, which isn't as pretty though: 这需要一个单独的print语句,虽然不是很漂亮:

objList.stream()
    .limit(objList.size()-1)
    .map(s -> s + ",")
    .forEach(System.out::print);
System.out.print(objList.get(objList.size()-1));

A fifth way is similar to the above, special-casing the first element instead of the last: 第五种方式与上面类似,特殊外壳的第一个元素而不是最后一个:

System.out.print(objList.get(0));
objList.stream()
    .skip(1)
    .map(s -> "," + s)
    .forEach(System.out::print);

Really, though the point of the joining collector is to do this ugly and irritating special-casing for you, so you don't have to do it yourself. 真的,虽然joining收藏家的目的是为你做这个丑陋和刺激性的特殊外壳,所以你不必自己做。

What about: 关于什么:

String concat = objList.stream().reduce(",", String::concat);
System.out.println(concat);
objList.stream().filter(s -> { return !s.equals("Bart") })

This will reduce the stream to the strings which are NOT equal to Bart 这将减少不等于Bart的字符串流

And this will print the last value of a map : 这将打印地图的最后一个值:

Map<Integer, String> map = new HashMap<>();
map.put(0, "a");
map.put(1, "c");
map.put(2, "d");

Integer lastIndex = map.keySet().size() - 1;

Stream<String> lastValueStream = map.values().stream().filter(s -> s.equals(map.get(lastIndex)));

We can also try using limit and skip methods of stream API to this problem. 我们也可以尝试使用流API的限制和跳过方法来解决这个问题。 Here is my try to this problem. 这是我尝试这个问题。

    returnData.stream().limit(returnData.size()-1).forEach(s->System.out.print(s+","));
    returnData.stream().skip(returnData.size()-1).forEach(s->System.out.print(s));

returnData is a List of Integers having values 2,4,7,14. returnData是一个值为2,4,7,14的整数列表。 The output will look like 2,4,7,14 输出看起来像2,4,7,14

try this, 试试这个,

int[] counter = new int[]{0};
objList.stream()
    .map(f -> (counter[0]++ > 0? "," : "") + f)
    .forEach(System.out::print);

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

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