What is the most elegant way to run a lambda for each element of a Java 8 stream and simultaneously count how...
up vote
3
down vote
favorite
What is the most elegant way to run a lambda for each element of a Java 8 stream and simultaneously count how many items were processed, assuming I want to process the stream only once and not mutate a variable outside the lambda?
java-8
add a comment |
up vote
3
down vote
favorite
What is the most elegant way to run a lambda for each element of a Java 8 stream and simultaneously count how many items were processed, assuming I want to process the stream only once and not mutate a variable outside the lambda?
java-8
1
What do you mean by process?map()
orforEach()
?
– biziclop
Feb 2 '17 at 11:51
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
What is the most elegant way to run a lambda for each element of a Java 8 stream and simultaneously count how many items were processed, assuming I want to process the stream only once and not mutate a variable outside the lambda?
java-8
What is the most elegant way to run a lambda for each element of a Java 8 stream and simultaneously count how many items were processed, assuming I want to process the stream only once and not mutate a variable outside the lambda?
java-8
java-8
asked Feb 2 '17 at 6:18
Gabriel C
4031417
4031417
1
What do you mean by process?map()
orforEach()
?
– biziclop
Feb 2 '17 at 11:51
add a comment |
1
What do you mean by process?map()
orforEach()
?
– biziclop
Feb 2 '17 at 11:51
1
1
What do you mean by process?
map()
or forEach()
?– biziclop
Feb 2 '17 at 11:51
What do you mean by process?
map()
or forEach()
?– biziclop
Feb 2 '17 at 11:51
add a comment |
4 Answers
4
active
oldest
votes
up vote
6
down vote
accepted
It might be tempting to use
long count = stream.peek(action).count();
and it may appear to work. However, peek
’s action will only be performed when an element is being processed, but for some streams, the count may be available without processing the elements. Java 9 is going to take this opportunity, which makes the code above fail to perform action
for some streams.
You can use a collect
operation that doesn’t allow to take short-cuts, e.g.
long count = stream.collect(
Collectors.mapping(s -> { action.accept(s); return s; }, Collectors.counting()));
or
long count = stream.collect(Collectors.summingLong(s -> { action.accept(s); return 1; }));
add a comment |
up vote
2
down vote
I would go with a reduce operation of some sort, something like this:
int howMany = Stream.of("a", "vc", "ads", "ts", "ta").reduce(0, (i, string) -> {
if (string.contains("a")) {
// process a in any other way
return i+1;
}
return i;
}, (left, right) -> null); // override if parallel stream required
System.out.println(howMany);
2
The question doesn’t mention conditional processing, but if this is intended, afilter
before counting would do. Besides—what’s stopping you from specifying the straight-forward merging function(left, right) -> left+right
rather than(left, right) -> null
? It doesn’t create any harm for sequential streams…
– Holger
Feb 2 '17 at 12:01
add a comment |
up vote
0
down vote
This can be done with peek
function, as it returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
AtomicInteger counter = new AtomicInteger(0);
elements
.stream()
.forEach(doSomething())
.peek(elem -> counter.incrementAndGet());
int elementsProcessed = counter.get();
3
and not mutate a variable outside the lambda
– Eugene
Feb 2 '17 at 8:47
4
Besides the fact that usingpeek
for this purpose is not recommended, it doesn’t even compile, if you try to chain apeek
after the terminalforEach
operation.
– Holger
Feb 2 '17 at 11:38
forEach
returns void and the suggested code doesn't compile.
– Gabriel C
Feb 2 '17 at 23:08
add a comment |
up vote
0
down vote
Streams are lazily evaluated and therefore processed in a single step, combining all intermediate operations when a final operation is called, no matter how many operations you perform over them.
This way, you don't have to worry because your stream will be processed at once. But the best way to perform some operation on each stream's element and count the number of elements processed depends on your goal.
Anyway, the two examples below don't mutate a variable to perform that count.
Both examples create a Stream of Strings, perform a trim() on each String to remove blank spaces and then, filter the Strings that have some content.
Example 1
Uses the peek method to perform some operation over each filtered string. In this case, just print each one. Finally, it just uses the count() to get how many Strings were processed.
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
long count = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.peek(System.out::println)
.count();
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", count);
Example 2
Uses the collect method after filtering and mapping to get all the processed Strings into a List. By this way, the List can be printed separately and the number of elements got from list.size()
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
List<String> list = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", list.size());
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
accepted
It might be tempting to use
long count = stream.peek(action).count();
and it may appear to work. However, peek
’s action will only be performed when an element is being processed, but for some streams, the count may be available without processing the elements. Java 9 is going to take this opportunity, which makes the code above fail to perform action
for some streams.
You can use a collect
operation that doesn’t allow to take short-cuts, e.g.
long count = stream.collect(
Collectors.mapping(s -> { action.accept(s); return s; }, Collectors.counting()));
or
long count = stream.collect(Collectors.summingLong(s -> { action.accept(s); return 1; }));
add a comment |
up vote
6
down vote
accepted
It might be tempting to use
long count = stream.peek(action).count();
and it may appear to work. However, peek
’s action will only be performed when an element is being processed, but for some streams, the count may be available without processing the elements. Java 9 is going to take this opportunity, which makes the code above fail to perform action
for some streams.
You can use a collect
operation that doesn’t allow to take short-cuts, e.g.
long count = stream.collect(
Collectors.mapping(s -> { action.accept(s); return s; }, Collectors.counting()));
or
long count = stream.collect(Collectors.summingLong(s -> { action.accept(s); return 1; }));
add a comment |
up vote
6
down vote
accepted
up vote
6
down vote
accepted
It might be tempting to use
long count = stream.peek(action).count();
and it may appear to work. However, peek
’s action will only be performed when an element is being processed, but for some streams, the count may be available without processing the elements. Java 9 is going to take this opportunity, which makes the code above fail to perform action
for some streams.
You can use a collect
operation that doesn’t allow to take short-cuts, e.g.
long count = stream.collect(
Collectors.mapping(s -> { action.accept(s); return s; }, Collectors.counting()));
or
long count = stream.collect(Collectors.summingLong(s -> { action.accept(s); return 1; }));
It might be tempting to use
long count = stream.peek(action).count();
and it may appear to work. However, peek
’s action will only be performed when an element is being processed, but for some streams, the count may be available without processing the elements. Java 9 is going to take this opportunity, which makes the code above fail to perform action
for some streams.
You can use a collect
operation that doesn’t allow to take short-cuts, e.g.
long count = stream.collect(
Collectors.mapping(s -> { action.accept(s); return s; }, Collectors.counting()));
or
long count = stream.collect(Collectors.summingLong(s -> { action.accept(s); return 1; }));
answered Feb 2 '17 at 11:37
Holger
159k23220422
159k23220422
add a comment |
add a comment |
up vote
2
down vote
I would go with a reduce operation of some sort, something like this:
int howMany = Stream.of("a", "vc", "ads", "ts", "ta").reduce(0, (i, string) -> {
if (string.contains("a")) {
// process a in any other way
return i+1;
}
return i;
}, (left, right) -> null); // override if parallel stream required
System.out.println(howMany);
2
The question doesn’t mention conditional processing, but if this is intended, afilter
before counting would do. Besides—what’s stopping you from specifying the straight-forward merging function(left, right) -> left+right
rather than(left, right) -> null
? It doesn’t create any harm for sequential streams…
– Holger
Feb 2 '17 at 12:01
add a comment |
up vote
2
down vote
I would go with a reduce operation of some sort, something like this:
int howMany = Stream.of("a", "vc", "ads", "ts", "ta").reduce(0, (i, string) -> {
if (string.contains("a")) {
// process a in any other way
return i+1;
}
return i;
}, (left, right) -> null); // override if parallel stream required
System.out.println(howMany);
2
The question doesn’t mention conditional processing, but if this is intended, afilter
before counting would do. Besides—what’s stopping you from specifying the straight-forward merging function(left, right) -> left+right
rather than(left, right) -> null
? It doesn’t create any harm for sequential streams…
– Holger
Feb 2 '17 at 12:01
add a comment |
up vote
2
down vote
up vote
2
down vote
I would go with a reduce operation of some sort, something like this:
int howMany = Stream.of("a", "vc", "ads", "ts", "ta").reduce(0, (i, string) -> {
if (string.contains("a")) {
// process a in any other way
return i+1;
}
return i;
}, (left, right) -> null); // override if parallel stream required
System.out.println(howMany);
I would go with a reduce operation of some sort, something like this:
int howMany = Stream.of("a", "vc", "ads", "ts", "ta").reduce(0, (i, string) -> {
if (string.contains("a")) {
// process a in any other way
return i+1;
}
return i;
}, (left, right) -> null); // override if parallel stream required
System.out.println(howMany);
edited Feb 2 '17 at 11:12
answered Feb 2 '17 at 8:43
Eugene
66.5k996159
66.5k996159
2
The question doesn’t mention conditional processing, but if this is intended, afilter
before counting would do. Besides—what’s stopping you from specifying the straight-forward merging function(left, right) -> left+right
rather than(left, right) -> null
? It doesn’t create any harm for sequential streams…
– Holger
Feb 2 '17 at 12:01
add a comment |
2
The question doesn’t mention conditional processing, but if this is intended, afilter
before counting would do. Besides—what’s stopping you from specifying the straight-forward merging function(left, right) -> left+right
rather than(left, right) -> null
? It doesn’t create any harm for sequential streams…
– Holger
Feb 2 '17 at 12:01
2
2
The question doesn’t mention conditional processing, but if this is intended, a
filter
before counting would do. Besides—what’s stopping you from specifying the straight-forward merging function (left, right) -> left+right
rather than (left, right) -> null
? It doesn’t create any harm for sequential streams…– Holger
Feb 2 '17 at 12:01
The question doesn’t mention conditional processing, but if this is intended, a
filter
before counting would do. Besides—what’s stopping you from specifying the straight-forward merging function (left, right) -> left+right
rather than (left, right) -> null
? It doesn’t create any harm for sequential streams…– Holger
Feb 2 '17 at 12:01
add a comment |
up vote
0
down vote
This can be done with peek
function, as it returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
AtomicInteger counter = new AtomicInteger(0);
elements
.stream()
.forEach(doSomething())
.peek(elem -> counter.incrementAndGet());
int elementsProcessed = counter.get();
3
and not mutate a variable outside the lambda
– Eugene
Feb 2 '17 at 8:47
4
Besides the fact that usingpeek
for this purpose is not recommended, it doesn’t even compile, if you try to chain apeek
after the terminalforEach
operation.
– Holger
Feb 2 '17 at 11:38
forEach
returns void and the suggested code doesn't compile.
– Gabriel C
Feb 2 '17 at 23:08
add a comment |
up vote
0
down vote
This can be done with peek
function, as it returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
AtomicInteger counter = new AtomicInteger(0);
elements
.stream()
.forEach(doSomething())
.peek(elem -> counter.incrementAndGet());
int elementsProcessed = counter.get();
3
and not mutate a variable outside the lambda
– Eugene
Feb 2 '17 at 8:47
4
Besides the fact that usingpeek
for this purpose is not recommended, it doesn’t even compile, if you try to chain apeek
after the terminalforEach
operation.
– Holger
Feb 2 '17 at 11:38
forEach
returns void and the suggested code doesn't compile.
– Gabriel C
Feb 2 '17 at 23:08
add a comment |
up vote
0
down vote
up vote
0
down vote
This can be done with peek
function, as it returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
AtomicInteger counter = new AtomicInteger(0);
elements
.stream()
.forEach(doSomething())
.peek(elem -> counter.incrementAndGet());
int elementsProcessed = counter.get();
This can be done with peek
function, as it returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
AtomicInteger counter = new AtomicInteger(0);
elements
.stream()
.forEach(doSomething())
.peek(elem -> counter.incrementAndGet());
int elementsProcessed = counter.get();
answered Feb 2 '17 at 8:44
m4tt
944
944
3
and not mutate a variable outside the lambda
– Eugene
Feb 2 '17 at 8:47
4
Besides the fact that usingpeek
for this purpose is not recommended, it doesn’t even compile, if you try to chain apeek
after the terminalforEach
operation.
– Holger
Feb 2 '17 at 11:38
forEach
returns void and the suggested code doesn't compile.
– Gabriel C
Feb 2 '17 at 23:08
add a comment |
3
and not mutate a variable outside the lambda
– Eugene
Feb 2 '17 at 8:47
4
Besides the fact that usingpeek
for this purpose is not recommended, it doesn’t even compile, if you try to chain apeek
after the terminalforEach
operation.
– Holger
Feb 2 '17 at 11:38
forEach
returns void and the suggested code doesn't compile.
– Gabriel C
Feb 2 '17 at 23:08
3
3
and not mutate a variable outside the lambda
– Eugene
Feb 2 '17 at 8:47
and not mutate a variable outside the lambda
– Eugene
Feb 2 '17 at 8:47
4
4
Besides the fact that using
peek
for this purpose is not recommended, it doesn’t even compile, if you try to chain a peek
after the terminal forEach
operation.– Holger
Feb 2 '17 at 11:38
Besides the fact that using
peek
for this purpose is not recommended, it doesn’t even compile, if you try to chain a peek
after the terminal forEach
operation.– Holger
Feb 2 '17 at 11:38
forEach
returns void and the suggested code doesn't compile.– Gabriel C
Feb 2 '17 at 23:08
forEach
returns void and the suggested code doesn't compile.– Gabriel C
Feb 2 '17 at 23:08
add a comment |
up vote
0
down vote
Streams are lazily evaluated and therefore processed in a single step, combining all intermediate operations when a final operation is called, no matter how many operations you perform over them.
This way, you don't have to worry because your stream will be processed at once. But the best way to perform some operation on each stream's element and count the number of elements processed depends on your goal.
Anyway, the two examples below don't mutate a variable to perform that count.
Both examples create a Stream of Strings, perform a trim() on each String to remove blank spaces and then, filter the Strings that have some content.
Example 1
Uses the peek method to perform some operation over each filtered string. In this case, just print each one. Finally, it just uses the count() to get how many Strings were processed.
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
long count = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.peek(System.out::println)
.count();
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", count);
Example 2
Uses the collect method after filtering and mapping to get all the processed Strings into a List. By this way, the List can be printed separately and the number of elements got from list.size()
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
List<String> list = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", list.size());
add a comment |
up vote
0
down vote
Streams are lazily evaluated and therefore processed in a single step, combining all intermediate operations when a final operation is called, no matter how many operations you perform over them.
This way, you don't have to worry because your stream will be processed at once. But the best way to perform some operation on each stream's element and count the number of elements processed depends on your goal.
Anyway, the two examples below don't mutate a variable to perform that count.
Both examples create a Stream of Strings, perform a trim() on each String to remove blank spaces and then, filter the Strings that have some content.
Example 1
Uses the peek method to perform some operation over each filtered string. In this case, just print each one. Finally, it just uses the count() to get how many Strings were processed.
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
long count = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.peek(System.out::println)
.count();
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", count);
Example 2
Uses the collect method after filtering and mapping to get all the processed Strings into a List. By this way, the List can be printed separately and the number of elements got from list.size()
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
List<String> list = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", list.size());
add a comment |
up vote
0
down vote
up vote
0
down vote
Streams are lazily evaluated and therefore processed in a single step, combining all intermediate operations when a final operation is called, no matter how many operations you perform over them.
This way, you don't have to worry because your stream will be processed at once. But the best way to perform some operation on each stream's element and count the number of elements processed depends on your goal.
Anyway, the two examples below don't mutate a variable to perform that count.
Both examples create a Stream of Strings, perform a trim() on each String to remove blank spaces and then, filter the Strings that have some content.
Example 1
Uses the peek method to perform some operation over each filtered string. In this case, just print each one. Finally, it just uses the count() to get how many Strings were processed.
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
long count = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.peek(System.out::println)
.count();
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", count);
Example 2
Uses the collect method after filtering and mapping to get all the processed Strings into a List. By this way, the List can be printed separately and the number of elements got from list.size()
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
List<String> list = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", list.size());
Streams are lazily evaluated and therefore processed in a single step, combining all intermediate operations when a final operation is called, no matter how many operations you perform over them.
This way, you don't have to worry because your stream will be processed at once. But the best way to perform some operation on each stream's element and count the number of elements processed depends on your goal.
Anyway, the two examples below don't mutate a variable to perform that count.
Both examples create a Stream of Strings, perform a trim() on each String to remove blank spaces and then, filter the Strings that have some content.
Example 1
Uses the peek method to perform some operation over each filtered string. In this case, just print each one. Finally, it just uses the count() to get how many Strings were processed.
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
long count = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.peek(System.out::println)
.count();
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", count);
Example 2
Uses the collect method after filtering and mapping to get all the processed Strings into a List. By this way, the List can be printed separately and the number of elements got from list.size()
Stream<String> stream =
Stream.of(" java", "", " streams", " are", " lazily ", "evaluated");
List<String> list = stream
.map(String::trim)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.printf(
"nNumber of non-empty strings after a trim() operation: %dnn", list.size());
edited Nov 10 at 23:33
answered Feb 2 '17 at 14:09
Manoel Campos
14018
14018
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f41995426%2fwhat-is-the-most-elegant-way-to-run-a-lambda-for-each-element-of-a-java-8-stream%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
What do you mean by process?
map()
orforEach()
?– biziclop
Feb 2 '17 at 11:51