I am looking for a method to assure all objects contained in a Collect (List) return a specified value from a predicate.
Pseudo Code:
Collections.assertTrue(List<Ballons>, isBluePredicate)
I do not see this being possible with the current API (maybe I am not looking in the proper place)
If this does exist would the function exit when it first encounters a false value?
The Iterables.all(Iterable, Predicate) method is the normal way to do this; the assertion would need to be your own.
Guava itself does not have any asserts. If I understand the question right you should be able to use Iterables.all
assert Iterables.all(balloonsList, isBlue) : "some aren't blue";
Documentation does not clarify whether the predicate is evaluated for rest of elements if one results in false, but I suspect they won't be. You can trivially check the source.
If you do need it to be evaluated for all elements then you should use filter and check the size of the result.
Related
I'm trying my hand at using Optional as much as I can over normal null checks; and I ran into a suggestion by my IDE (IntelliJ):
Can be replaced by a singular expression in functional style.
Here is the code in question, the line in question:
Entry entry = maybeBytes.isPresent() ? Entry.deserialize(maybeBytes.get()) : new Entry();
I've looked a bit here, but couldn't find a usage or at least see one that would fit my case here. I'm pretty new to the lambda features.
How about:
Entry entry = maybeBytes.map(Entry::deserialize).orElseGet(Entry::new);
If maybeBytes contains a value, it will be passed to the function you provide to map(), and you'll get an Optional<Entry> with the result (and if maybeBytes was empty, you'll get an empty Optional<Entry>). orElseGet() will give you the contents of the Optional<Entry> if it's nonempty, and otherwise, it will give you the result of evaluating the function you pass to it (in this case, the constructor of Entry).
Pressing Alt+Enter when you see such suggestions will apply them, and you'll see the result yourself :)
In my case it was orElse() which fit to my needs. I do not needed to do extra deserialization.
instead of isPresent() combined with get() certainly does the trickā¦
return maybeBytes.isPresent() ? maybeBytes.get() : new Entry();
you can use
return maybeBytes.orElse(new Entry());
I want to use Optional for a method which returns a List
Lets say the function is
public Output getListOfSomething() {
// In some cases there is nothing to return and hence it makes sense to have return
// type as Optional here
}
Hence the function looks like :
public Optional<List<String>> getListOfSomething() {
// return something only when there is some valid list
}
Now I want to do something if the list is present so something like :
Optional<List<String>> listOfSomething = getListOfSomething();
int size = 0;
listOfSomething.ifPresent(size = listOfSomething.get().size());
I am new to Optional and have gone through the articles about Optional and it seems like this should work however am getting syntax error in my IDE :
method ifPresent is not applicable for the arguments (void).
I wanted to get some help from developers who might be more fluent with lamdas in java 8.
It's important to think about the Semantics here.
Your method could return a List, or "no list".
If it returns a List, it could return an Empty list.
You should ask, "is there a semantic reason to distinguish between an Empty List, and No List?" Sometimes there is a good design reason to make the difference, but it is rare. Think long and hard before deciding that Empty and Null are different in your case. Part of the reason to avoid No List, is that it reduces "special cases" that the client code has to consider. For example, if they have to do something for every item returned, but you could also return null, they have to do a special check for null before going into a for each loop. A for each does nothing if the list is empty.
If a "No List" is distinct from an "Empty List" in your problem domain, then it is sometimes useful to return wrapper class that helps client code distinguish between those conditions, and handle them appropriately. Optional is one such generic class, but your domain may call for something more specific (even if it mimics the functionality of Optional, it might have better semantic definition).
The true functional-programming way is the following:
size = listOfSomething.map(List::size).orElse(0);
But it would be much better to return an empty List instead of Optional.
ifPresent requires a Consumer interface to work. You could do the following:
Optional<List<String>> listOfSomething = getListOfSomething();
Integer[] size = {0};
listOfSomething.ifPresent(list -> size[0]=list.size())
But as stated by Tagir Valeev it would be better to do:
size = listOfSomething.map(List::size).orElse(0);
And it would also be better to return an empty List or even a Stream maybe.
I am trying to change some for-each loops to lambda forEach()-methods to discover the possibilities of lambda expressions. The following seems to be possible:
ArrayList<Player> playersOfTeam = new ArrayList<Player>();
for (Player player : players) {
if (player.getTeam().equals(teamName)) {
playersOfTeam.add(player);
}
}
With lambda forEach()
players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});
But the next one doesn't work:
for (Player player : players) {
if (player.getName().contains(name)) {
return player;
}
}
with lambda
players.forEach(player->{if (player.getName().contains(name)) {return player;}});
Is there something wrong in the syntax of the last line or is it impossible to return from forEach() method?
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 a Stream<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 is Collectors.toList().
This also incorporates two other points:
Code against interfaces, so code against List<E> over ArrayList<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.
If you want to return a boolean value, then you can use something like this (much faster than filter):
players.stream().anyMatch(player -> player.getName().contains(name));
This what helped me:
List<RepositoryFile> fileList = response.getRepositoryFileList();
RepositoryFile file1 = fileList.stream().filter(f -> f.getName().contains("my-file.txt")).findFirst().orElse(null);
Taken from Java 8 Finding Specific Element in List with Lambda
You can also throw an exception:
Note:
For the sake of readability each step of stream should be listed in new line.
players.stream()
.filter(player -> player.getName().contains(name))
.findFirst()
.orElseThrow(MyCustomRuntimeException::new);
if your logic is loosely "exception driven" such as there is one place in your code that catches all exceptions and decides what to do next. Only use exception driven development when you can avoid littering your code base with multiples try-catch and throwing these exceptions are for very special cases that you expect them and can be handled properly.)
This question is a bit hard to explain so please look at the increasingPath function in the code here. Now assuming the path does not exist, and arraylist pointPath with 0 size is returned.
However I have read that we must use Collections.emptyList, but how do I use it in this scenario, when I already have a probably empty list called pointPath ? If not to use Collections.emptyList then when to use it ?
I think what you're supposed to do is use Collections.EmptyList for comparisons and returning.
for example:
if (pointPath.equals(Collections.emptyList()){
return Collections.emptyList();
}
I don't think it changes how your program will execute, but it makes the code readable and self-documenting.
Simply check
if (pointPath.isEmpty()){
return Collections.emptyList();
}
The only difference from actually returning a your list that is accidentally empty is that Collections.emptyList() is immutable list. If that is not of any value to you, I'd return your real list. That way there is less code to read.
Assume I want to unit test a method with this signature:
List<MyItem> getMyItems();
Assume MyItem is a Pojo that has many properties, one of which is "name", accessed via getName().
All I care about verifying is that the List<MyItem>, or any Iterable, contains two MyItem instances, whose "name" properties have the values "foo" and "bar". If any other properties don't match, I don't really care for the purposes of this test. If the names match, it's a successful test.
I would like it to be one-liner if possible. Here is some "pseudo-syntax" of the kind of thing I would like to do.
assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"});
Would Hamcrest be good for this type of thing? If so, what exactly would be the hamcrest version of my pseudo-syntax above?
Thank you #Razvan who pointed me in the right direction. I was able to get it in one line and I successfully hunted down the imports for Hamcrest 1.3.
the imports:
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
the code:
assertThat( myClass.getMyItems(), contains(
hasProperty("name", is("foo")),
hasProperty("name", is("bar"))
));
AssertJ provides an excellent feature in extracting() : you can pass Functions to extract fields. It provides a check at compile time.
You could also assert the size first easily.
It would give :
import static org.assertj.core.api.Assertions;
Assertions.assertThat(myClass.getMyItems())
.hasSize(2)
.extracting(MyItem::getName)
.containsExactlyInAnyOrder("foo", "bar");
containsExactlyInAnyOrder() asserts that the list contains only these values whatever the order.
To assert that the list contains these values whatever the order but may also contain other values use contains() :
.contains("foo", "bar");
As a side note : to assert multiple fields from elements of a List , with AssertJ we do that by wrapping expected values for each element into a tuple() function :
import static org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple;
Assertions.assertThat(myClass.getMyItems())
.hasSize(2)
.extracting(MyItem::getName, MyItem::getOtherValue)
.containsExactlyInAnyOrder(
tuple("foo", "OtherValueFoo"),
tuple("bar", "OtherValueBar")
);
Its not especially Hamcrest, but I think it worth to mention here. What I use quite often in Java8 is something like:
assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName())));
(Edited to Rodrigo Manyari's slight improvement. It's a little less verbose. See comments.)
It may be a little bit harder to read, but I like the type and refactoring safety.
Its also cool for testing multiple bean properties in combination. e.g. with a java-like && expression in the filter lambda.
Try:
assertThat(myClass.getMyItems(),
hasItem(hasProperty("YourProperty", is("YourValue"))));
Assertj is good at this.
import static org.assertj.core.api.Assertions.assertThat;
assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar");
Big plus for assertj compared to hamcrest is easy use of code completion.
As long as your List is a concrete class, you can simply call the contains() method as long as you have implemented your equals() method on MyItem.
// given
// some input ... you to complete
// when
List<MyItems> results = service.getMyItems();
// then
assertTrue(results.contains(new MyItem("foo")));
assertTrue(results.contains(new MyItem("bar")));
Assumes you have implemented a constructor that accepts the values you want to assert on. I realise this isn't on a single line, but it's useful to know which value is missing rather than checking both at once.
AssertJ 3.9.1 supports direct predicate usage in anyMatch method.
assertThat(collection).anyMatch(element -> element.someProperty.satisfiesSomeCondition())
This is generally suitable use case for arbitrarily complex condition.
For simple conditions I prefer using extracting method (see above) because resulting iterable-under-test might support value verification with better readability.
Example: it can provide specialized API such as contains method in Frank Neblung's answer. Or you can call anyMatch on it later anyway and use method reference such as "searchedvalue"::equals. Also multiple extractors can be put into extracting method, result subsequently verified using tuple().
Alternatively to hasProperty you can try hamcrest-more-matchers where matcher with extracting function. In your case it will look like:
import static com.github.seregamorph.hamcrest.MoreMatchers.where;
assertThat(myClass.getMyItems(), contains(
where(MyItem::getName, is("foo")),
where(MyItem::getName, is("bar"))
));
The advantages of this approach are:
It is not always possible to verify by field if the value is computed in get-method
In case of mismatch there should be a failure message with diagnostics (pay attention to resolved method reference MyItem.getName:
Expected: iterable containing [Object that matches is "foo" after call
MyItem.getName, Object that matches is "bar" after call MyItem.getName]
but: item 0: was "wrong-name"
It works in Java 8, Java 11 and Java 14
With Stream you can also do:
List<String> actual = myList.stream().map(MyClass::getName).collect(toList());
assertThat(actual, hasItem("expectedString1"));
Because with anyMatch() or allMatch(), you know some values in your list are in the list, but there is possibility that your actual list only contains 5 values while in anyMatch() you have 6; you don't know if all values are present or not. With hasItem(), you indeed check every value you want.