If you need this, you shouldn't use forEach, but one of the other methods available on streams; which one, depends on what your goal is.
For example, if the goal of this loop is to find the first element which matches some predicate:
Optional<SomeObject> result =
someObjects.stream().filter(obj -> some_condition_met).findFirst();
(Note: This will not iterate the whole collection, because streams are lazily evaluated - it will stop at the first object that matches the condition).
If you just want to know if there's an element in the collection for which the condition is true, you could use anyMatch:
boolean result = someObjects.stream().anyMatch(obj -> some_condition_met);
Answer from Jesper on Stack OverflowIf you need this, you shouldn't use forEach, but one of the other methods available on streams; which one, depends on what your goal is.
For example, if the goal of this loop is to find the first element which matches some predicate:
Optional<SomeObject> result =
someObjects.stream().filter(obj -> some_condition_met).findFirst();
(Note: This will not iterate the whole collection, because streams are lazily evaluated - it will stop at the first object that matches the condition).
If you just want to know if there's an element in the collection for which the condition is true, you could use anyMatch:
boolean result = someObjects.stream().anyMatch(obj -> some_condition_met);
A return in a lambda equals a continue in a for-each, but there is no equivalent to a break. You can just do a return to continue:
someObjects.forEach(obj -> {
if (some_condition_met) {
return;
}
})
I guess you want to do this:
public boolean find(){
return someObjects.stream().anyMatch(o -> your_condition);
}
The forEach method in a Collection expects a Consumer which means a function that takes a value, but doesn't return anything. That's why you can't use return true; but a return; works fine.
I you want to break out of the loop when your condition is met, it's better to use a simple for(...) loop. I assumed that the type of obj is Object:
for (Object obj : someObjects) {
if (some_condition_met) {
return true;
}
}
return false;
Return from lambda forEach() in java - Stack Overflow
How can Stream forEach method accept boolean?
lambda - Java how to use stream map to return boolean - Stack Overflow
java - Iterate through ArrayList with If condition and return boolean flag with stream api - Stack Overflow
I'd change Boolean.FALSE to false and Boolean.TRUE to true. Using the constants objects from Boolean is rather unnecessary since the method returns with primitive boolean.
Though for loop is enough, you can rewrite using Guava if you like lambdas:
public boolean checkNameStartsWith(List<Foo> foos){
return Iterables.all(foos, new Predicate<Foo>() {
public boolean apply(Foo foo) {
return foo.getName().startsWith("bar");
}
});
}
The return there is returning from the lambda expression rather than from the containing method. Instead of forEach you need to filter the stream:
players.stream().filter(player -> player.getName().contains(name))
.findFirst().orElse(null);
Here filter restricts the stream to those items that match the predicate, and findFirst then returns an Optional with the first matching entry.
This looks less efficient than the for-loop approach, but in fact findFirst() can short-circuit - it doesn't generate the entire filtered stream and then extract one element from it, rather it filters only as many elements as it needs to in order to find the first matching one. You could also use findAny() instead of findFirst() if you don't necessarily care about getting the first matching player from the (ordered) stream but simply any matching item. This allows for better efficiency when there's parallelism involved.
I suggest you to first try to understand Java 8 in the whole picture, most importantly in your case it will be streams, lambdas and method references.
You should never convert existing code to Java 8 code on a line-by-line basis, you should extract features and convert those.
What I identified in your first case is the following:
- You want to add elements of an input structure to an output list if they match some predicate.
Let's see how we do that, we can do it with the following:
List<Player> playersOfTeam = players.stream()
.filter(player -> player.getTeam().equals(teamName))
.collect(Collectors.toList());
What you do here is:
- Turn your input structure into a stream (I am assuming here that it is of type
Collection<Player>, now you have aStream<Player>. - Filter out all unwanted elements with a
Predicate<Player>, mapping every player to the boolean true if it is wished to be kept. - Collect the resulting elements in a list, via a
Collector, here we can use one of the standard library collectors, which isCollectors.toList().
This also incorporates two other points:
- Code against interfaces, so code against
List<E>overArrayList<E>. - Use diamond inference for the type parameter in
new ArrayList<>(), you are using Java 8 after all.
Now onto your second point:
You again want to convert something of legacy Java to Java 8 without looking at the bigger picture. This part has already been answered by @IanRoberts, though I think that you need to do players.stream().filter(...)... over what he suggested.
Hi, studying for Java 17 certificate. Came to this question:
void brew() throws IOException {
final var m = Path.of("coffee");
Files.walk(m)
.filter(Files::isDirectory)
.forEach(Files::isDirectory);
}I see a boolean supplied for forEach() method. My answer was "Does not compile". But it actually does compile. I dont get why. If I try forEach(true) it does not compile. So how does code in the example compile? forEch() accepts Consumer<>, not boolean :?
you are using the stream wrong...
you dont need to do a foreach on the stream, invoke the anyMatch instead
public boolean status(List<String> myArray) {
return myArray.stream().anyMatch(item -> here the logic related to x.status());
}
It looks like helpFunction(item) returns some instance of some class that has a boolean status() method, and you want your method to return true if helpFunction(item).status() is true for any element of your Stream.
You can implement this logic with anyMatch:
public boolean status(List<String> myArray) {
return myArray.stream()
.anyMatch(item -> helpFunction(item).status());
}
All you care about is if at least one input from your list is bigger than 10, thus anyMatch:
boolean isTrue = intList.stream()
.anyMatch(x -> x > 10);
you iterate a List of Integer. So use
Collection.stream()you compare numeric value. So use
Stream.mapToInt()to work withintrather thanIntegerthat is more efficient. Here it doesn't change many things but if you change the stream to do some other numerical operations, you already use the correct way.you value a boolean (result) as soon as a condition is met. Otherwise false I assume. So use
Stream.anyMatch(Predicate).
So this corresponds :
boolean result =
intList.stream()
.mapToInt(i-> i)
.anyMatch(i-> i > 10);
The behavior you're describing is exactly what the anyMatch method is designed for:
boolean hasName = mySet.stream().anyMatch(c -> c.getName().equals("Darth Vader"));
What you need here is filtering operation with combination of findFirst() which returns Optional.
If you sure that there is such item in your set, then you may safely call get() after findFirst(), but in general I advice you to provide a default value using orElse or throw exception using orElseThrow on that Optional or use one of other useful methods. Choose wisely what fits your case :)
set.stream()
.filter(character -> character.getName().equals("Darth Veider"))
.findFirst()