Is there analog of everyItem() from Hamcrest in AssertJ?
I have a list of emails and need to do Assertion to check that each email contains substring "alex". Currently the only way I can do it with AssertJ is as follows:
List<String> actual = Arrays.asList("alex#gmail.com", "alex1#gmail.com", "ale2#hotmail.com", "bred#gmail.com");
SoftAssertions softly = new SoftAssertions();
for(String email: actual ) {
softly.assertThat(email).contains("alex");
}
softly.assertAll();
Can be done without Soft Assertions there as well, but I'd prefer to check all the item of the list.
Is there any more compact way to do so? To be specific, is there a way in AssertJ to check each item of the list to match a substring?
In Hamcrest I can do it in one line:
assertThat(actual, everyItem(containsString("alex")));
But in AssertJ looks like in any way I have to manually iterate through the list.
Assertj 3.6.0 introduced the allSatisfy assertion, which allows you to perform scoped assertions on each element of the iterable.
Therefore you could do what you want with
assertThat(actual).allSatisfy(elem -> assertThat(elem).contains("alex"));
I found 2 solutions:
1) use java 8
actual.forEach( val -> softly.assertThat(val).contains("alex"));
2) make an utility class
public class AssertUtils {
public static Condition<String> ContainsCondition(String val) {
return new Condition<String>() {
#Override
public boolean matches(String value) {
return value.contains(val);
}
};
}
}
and use it:
softly.assertThat(actual).are(AssertUtils.ContainsCondition("alex"));
You can build AssertJ condition with predicate and use are/have assertion:
#Test
public void condition_built_with_predicate_example() {
Condition<String> fairyTale = new Condition<String>(s -> s.startsWith("Once upon a time"), "a %s tale", "fairy");
String littleRedCap = "Once upon a time there was a dear little girl ...";
String cindirella = "Once upon a time there was a ...";
assertThat(asList(littleRedCap, cindirella)).are(fairyTale);
}
Edit: As pointed by Dan I would now use allSatisfy.
I prefer to use this form of allMatch as follow:
assertThat(movies).extracting("title").allMatch(s -> s.toString().contains("the"));
I just rely on Java 8 stream functionality for that kind of stuff:
assertThat(actual.stream().allMatch(s -> s.contains("alex"))).isTrue();
Related
I couldn't wrap my head around writing the below condition using Java Streams. Let's assume that I have a list of elements from the periodic table. I've to write a method that returns a String by checking whether the list has Silicon or Radium or Both. If it has only Silicon, method has to return Silicon. If it has only Radium, method has to return Radium. If it has both, method has to return Both. If none of them are available, method returns "" (default value).
Currently, the code that I've written is below.
String resolve(List<Element> elements) {
AtomicReference<String> value = new AtomicReference<>("");
elements.stream()
.map(Element::getName)
.forEach(name -> {
if (name.equalsIgnoreCase("RADIUM")) {
if (value.get().equals("")) {
value.set("RADIUM");
} else {
value.set("BOTH");
}
} else if (name.equalsIgnoreCase("SILICON")) {
if (value.get().equals("")) {
value.set("SILICON");
} else {
value.set("BOTH");
}
}
});
return value.get();
}
I understand the code looks messier and looks more imperative than functional. But I don't know how to write it in a better manner using streams. I've also considered the possibility of going through the list couple of times to filter elements Silicon and Radium and finalizing based on that. But it doesn't seem efficient going through a list twice.
NOTE : I also understand that this could be written in an imperative manner rather than complicating with streams and atomic variables. I just want to know how to write the same logic using streams.
Please share your suggestions on better ways to achieve the same goal using Java Streams.
It could be done with Stream IPA in a single statement and without multiline lambdas, nested conditions and impure function that changes the state outside the lambda.
My approach is to introduce an enum which elements correspond to all possible outcomes with its constants EMPTY, SILICON, RADIUM, BOTH.
All the return values apart from empty string can be obtained by invoking the method name() derived from the java.lang.Enum. And only to caver the case with empty string, I've added getName() method.
Note that since Java 16 enums can be declared locally inside a method.
The logic of the stream pipeline is the following:
stream elements turns into a stream of string;
gets filtered and transformed into a stream of enum constants;
reduction is done on the enum members;
optional of enum turs into an optional of string.
Implementation can look like this:
public static String resolve(List<Element> elements) {
return elements.stream()
.map(Element::getName)
.map(String::toUpperCase)
.filter(str -> str.equals("SILICON") || str.equals("RADIUM"))
.map(Elements::valueOf)
.reduce((result, next) -> result == Elements.BOTH || result != next ? Elements.BOTH : next)
.map(Elements::getName)
.orElse("");
}
enum
enum Elements {EMPTY, SILICON, RADIUM, BOTH;
String getName() {
return this == EMPTY ? "" : name(); // note name() declared in the java.lang.Enum as final and can't be overridden
}
}
main
public static void main(String[] args) {
System.out.println(resolve(List.of(new Element("Silicon"), new Element("Lithium"))));
System.out.println(resolve(List.of(new Element("Silicon"), new Element("Radium"))));
System.out.println(resolve(List.of(new Element("Ferrum"), new Element("Oxygen"), new Element("Aurum")))
.isEmpty() + " - no target elements"); // output is an empty string
}
output
SILICON
BOTH
true - no target elements
Note:
Although with streams you can produce the result in O(n) time iterative approach might be better for this task. Think about it this way: if you have a list of 10.000 elements in the list and it starts with "SILICON" and "RADIUM". You could easily break the loop and return "BOTH".
Stateful operations in the streams has to be avoided according to the documentation, also to understand why javadoc warns against stateful streams you might take a look at this question. If you want to play around with AtomicReference it's totally fine, just keep in mind that this approach is not considered to be good practice.
I guess if I had implemented such a method with streams, the overall logic would be the same as above, but without utilizing an enum. Since only a single object is needed it's a reduction, so I'll apply reduce() on a stream of strings, extract the reduction logic with all the conditions to a separate method. Normally, lambdas have to be well-readable one-liners.
Collect the strings to a unique set. Then check containment in constant time.
Set<String> names = elements.stream().map(Element::getName).map(String::toLowerCase).collect(toSet());
boolean hasSilicon = names.contains("silicon");
boolean hasRadium = names.contains("radium");
String result = "";
if (hasSilicon && hasRadium) {
result = "BOTH";
} else if (hasSilicon) {
result = "SILICON";
} else if (hasRadium) {
result = "RADIUM";
}
return result;
i have used predicate in filter to for radium and silicon and using the resulted set i am printing the result.
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Test {
public static void main(String[] args) {
List<Element> elementss = new ArrayList<>();
Set<String> stringSet = elementss.stream().map(e -> e.getName())
.filter(string -> (string.equals("Radium") || string.equals("Silicon")))
.collect(Collectors.toSet());
if(stringSet.size()==2){
System.out.println("both");
}else if(stringSet.size()==1){
System.out.println(stringSet);
}else{
System.out.println(" ");
}
}
}
You could save a few lines if you use regex, but I doubt if it is better than the other answers:
String resolve(List<Element> elements) {
String result = elements.stream()
.map(Element::getName)
.map(String::toUpperCase)
.filter(str -> str.matches("RADIUM|SILICON"))
.sorted()
.collect(Collectors.joining());
return result.matches("RADIUMSILICON") ? "BOTH" : result;
}
I have a java class with 3 boolean property like this
boolean isActive;
boolean isEnable;
boolean isNew;
every property is related to an enum (e.g. ACTIVE,ENABLE,NEW).
I want to have 2 lists of enum. One which has only the enums related to true property value and one for the false one.
just to be clear. using if-else statement I could have
Set<FlagEnum> flagSet = new HashSet<>();
Set<FlagEnum> falseFlagSet = new HashSet<>();
if (object.isActive()) {
flagSet.add(ACTIVE);
} else {
falseFlagSet.add(ACTIVE);
}
if (object.isEnable()) {
flagSet.add(ENABLE);
} else {
falseFlagSet.add(ENABLE);
}
if (object.isNew()) {
flagSet.add(NEW);
} else {
falseFlagSet.add(NEW);
}
is there a way to avoid all these if-else?
I tried with something like
Map<boolean, List<Pair<boolean, FlagEnum>>> res = Stream.of(
new Pair<>(object.isActive(), ACTIVE),
new Pair<>(object.isNew(), NEW),
new Pair<>(object.isEnable(), ENABLE))
.collect(Collectors.partitioningBy(Pair::getKey));
but the resulted structure is an additional complexity which I would like to avoid.
In my real case, I have more than 15 boolean properties...
You can simplify this in various ways. Which of them make sense, depends on your exact requirements.
You can derive the falseFlagSet trivially from the flagSet using EnumSet.complementOf after populating the flagSet:
EnumSet<FlagEnum> falseFlagSet = EnumSet.complementOf(flagSet);
This assumes that all FlagEnum values have corresponding flags. If that's not the case then you need to construct a EnumSet with all enums that have flags and subtract flagSet from that using removeAll.
#1 already removes the need for the else in your cascade, simplifying the code to
if (object.isActive()) {
flagSet.add(ACTIVE);
}
if (object.isEnable()) {
flagSet.add(ENABLE);
}
if (object.isNew()) {
flagSet.add(NEW);
}
If you have enough different flags, then you can create a mapping from getter method to FlagEnum value like this:
Map<Function<YourClass,Boolean>,FlagEnum> GETTERS = Map.of(
YourClass::isActive, FlagEnum.ACTIVE,
YourClass::isNew, FlagEnum.NEW,
YourClass::isEnable, FlagEnum.ENABLE);
Then you can use this to make the whole process data-driven:
EnumSet<FlagEnum> getFlagSet(YourClass yourObject) {
EnumSet<FlagEnum> result = EnumSet.noneOf(FlagEnum.class);
for (Map.Entry<Function<YourClass,Boolean>, FlagEnum> getter : GETTERS.entrySet()) {
if (getter.getKey().apply(yourObject)) {
result.add(getter.getValue());
}
}
return result;
}
If the number of flags is very big, then you could switch entirely to reflection and detect the flags and matching getters dynamically using string comparison, but I would not suggest that approach. If you need something like that then you probably should switch to a framework that supports that kind of feature and not implement it yourself.
That last two obviously only makes sense when the number of flags is big. If it's actually just 3 flags, then I wouldn't mind and just have 3 simple if statements.
As a slight tangent: GETTERS above should definitely be an immutable map (wrap it in Collections.unmodifiableMap or use something like Guava ImmutableMap) and it could be argued that the same applies to the return value of the getFlagSet method. I've left those out for succinctness.
You can use a private helper method for this.
private void addFlagSet(boolean condition, FlagEnum flagEnum,
Set<FlagEnum> flagSet, Set<FlagEnum> falseFlagSet) {
Set<FlagEnum> chosenFlagSet = condition ? flagSet: falseFlagSet;
chosenFlagSet.add(flagEnum);
}
Call it as:
addFlagSet(object.isActive(), FlagEnum.ACIVE, flagSet, falseFlagSet);
addFlagSet(object.isNew(), FlagEnum.NEW, flagSet, falseFlagSet);
addFlagSet(object.isEnable(), FlagEnum.ENABLE, flagSet, falseFlagSet);
You could probably use Reflection to get all methods, then check if a getReturnType() == boolean.class. Problem is the connection between the method's name and the enum. If every single one is named like the method without the 'is', you could use FlagEnum.valueOf() to retrieve the enum value from the method name and use it.
I think this could be the easiest and clearest way to do what I need
Map<Boolean, Set<FlagEnum>> flagMap = new HashMap<>();
flagMap.computeIfAbsent(object.isActive(), h -> new HashSet()).add(ACTIVE);
flagMap.computeIfAbsent(object.isEnabled(), h -> new HashSet()).add(ENABLE);
flagMap.computeIfAbsent(object.isNew(), h -> new HashSet()).add(NEW);
//to get TRUE set simply :
flagMap.get(true);
what do you think?
I have a String[] of user input and I want to filter a Collection of devices based on if the hostName of the device contains any of the user input.
I'm trying to follow the lesson https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html to do this.
interface PredicateOperation{
Predicate operation(String[] input);
}
public Predicate getPredicate(String[] input, PredicateOperation op){
return op.operation(input);
}
private TufinDeviceCollection<TufinDevice> filter(TufinDeviceCollection<TufinDevice> devices) {
//Check if any HostNames of the devices contain any of the items in String[] modelContains
devices = devices.stream()
.sequential()
.filter(//How do i create this predicate?)//we need to create the lamda expression to evaulate if the hostName of device d contains any of the items String[] userInput
.collect(Collectors.toCollection(TufinDeviceCollection<TufinDevice>::new));
}
It is unclear to me how to define the PredicateOperation that goes in .filter(..)
.filter(device -> Arrays.stream(userInput)
.anyMatch(input -> device.getHostName().contains(input)))
But you need String[] userInput to be accessible from the filter method.
I guess it was an attempt to write own #FunctionalInterface to replace the standard Predicate<T>.
interface PredicateOperation {
Predicate operation(String[] input);
}
It's not very practical, though.
PredicateOperation operation = (String[] input) -> ((Object o) -> true);
Why would I need to return a Predicate if I can return a result? A little enhanced version would be
interface PredicateOperation {
boolean operation(String[] input);
}
and
PredicateOperation operation = (String[] input) -> true;
which still isn't particularly useful for Stream API since Stream#filter expects a java.util.function.Predicate<T>, not your type.
And, yes, stop using raw Predicates.
device -> Stream.of(inputs).anyMatch(input -> device.hostName.contains(input))
I prefer to separate predicate on a separate line and apply it later on filter() for readability and re-usability purposes. So the code would be somewhat like :
private TufinDeviceCollection<TufinDevice> filter(TufinDeviceCollection<TufinDevice> devices) {
Predicate< ? super TufinDevice> deviceFilter = device -> Arrays.stream(userInput)
.anyMatch(input -> device.getHostName().contains(input));
devices = devices.stream()
.sequential()
.filter(deviceFilter)
.collect(Collectors.toCollection(TufinDeviceCollection<TufinDevice>::new));
}
I have an Try<Option<Foo>>. I want to flatMap Foo into a Bar, using it using an operation that can fail. It's not a failure if my Option<Foo> is an Option.none(), (and the Try was a success) and in this case there's nothing to do.
So I have code like this, which does work:
Try<Option<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo).map(Option::of) /* ew */)
.getOrElse(Try.success(Option.none()); // double ew
}
Try<Bar> mappingFunc(Foo foo) throws IOException {
// do some mapping schtuff
// Note that I can never return null, and a failure here is a legitimate problem.
// FWIW it's Jackson's readValue(String, Class<?>)
}
I then call it like:
fooOptionTry.flatMap(this::myFlatMappingFunc);
This does work, but it looks really ugly.
Is there a better way to flip the Try and Option around?
Note 1: I actively do not want to call Option.get() and catch that within the Try as it's not semantically correct. I suppose I could recover the NoSuchElementException but that seems even worse, code-wise.
Note 2 (to explain the title): Naively, the obvious thing to do is:
Option<Try<Bar>> myFlatMappingFunc(Option<Foo> fooOpt) {
return fooOpt.map(foo -> mappingFunc(foo));
}
except this has the wrong signature and doesn't let me map with the previous operation that could have failed and also returned a successful lack of value.
When you are working with monads, each monad type combine only with monads of same type. This is usually a problem because the code will come very unreadable.
In the Scala world, there are some solutions, like the OptionT or EitherT transformers, but do this kind of abstractions in Java could be difficult.
The simple solution is to use only one monad type.
For this case, I can think in two alternatives:
transform fooOpt to Try<Foo> using .toTry()
transform both to Either using .toEither()
Functional programmers are usually more comfortable with Either because exceptions will have weird behaviors, instead Either usually not, and both works when you just want to know why and where something failed.
Your example using Either will look like this:
Either<String, Bar> myFlatMappingFunc(Option<Foo> fooOpt) {
Either<String, Foo> fooE = fooOpt.toEither("Foo not found.");
return fooE.flatMap(foo -> mappingFunc(foo));
}
// Look mom!, not "throws IOException" or any unexpected thing!
Either<String, Bar> mappingFunc(Foo foo) {
return Try.of(() -> /*do something dangerous with Foo and return Bar*/)
.toEither().mapLeft(Throwable::getLocalizedMessage);
}
I believe this is simply a sequence function (https://static.javadoc.io/io.vavr/vavr/0.9.2/io/vavr/control/Try.html#sequence-java.lang.Iterable-) that you are looking for:
Try.sequence(optionalTry)
You can combine Try.sequence and headOption functions and create a new transform function with a little better look, in my opinion, also you can use generic types to get a more reusable function :) :
private static <T> Try<Option<T>> transform(Option<Try<T>> optT) {
return Try.sequence(optT.toArray()).map(Traversable::headOption);
}
If I understand correctly, you want to :
keep the first failure if happens
swap the second when mapping to json for an empty option.
Isn t it simpler if you decompose your function in such a way:
public void keepOriginalFailureAndSwapSecondOneToEmpty() {
Try<Option<Foo>> tryOptFoo = null;
Try<Option<Bar>> tryOptBar = tryOptFoo
.flatMap(optFoo ->
tryOptionBar(optFoo)
);
}
private Try<Option<Bar>> tryOptionBar(Option<Foo> optFoo) {
return Try.of(() -> optFoo
.map(foo -> toBar(foo)))
.orElse(success(none())
);
}
Bar toBar(Foo foo) throws RuntimeException {
return null;
}
static class Bar {
}
static class Foo {
}
The solution of throughnothing and durron597 helped me there. This is my groovy test case:
def "checkSomeTry"() {
given:
def ex = new RuntimeException("failure")
Option<Try<String>> test1 = Option.none()
Option<Try<String>> test2 = Option.some(Try.success("success"))
Option<Try<String>> test3 = Option.some(Try.failure(ex))
when:
def actual1 = Try.sequence(test1).map({ t -> t.toOption() })
def actual2 = Try.sequence(test2).map({ t -> t.toOption() })
def actual3 = Try.sequence(test3).map({ t -> t.toOption() })
then:
actual1 == Try.success(Option.none())
actual2 == Try.success(Option.some("success"))
actual3 == Try.failure(ex)
}
How do I code in Java the following python lines?
a = [True, False]
any (a)
all (a)
inb4 "What have you tried?"
The sledge-hammer way would be writing my own all and any methods (and obviously a class to host them):
public boolean any (boolean [] items)
{
for (boolean item: items)
if (item) return true;
return false;
}
//other way round for all
But I don't plan on re-inventing the wheel and there must be a neat way to do this...
any() is the same thing as Collection#contains(), which is part of the standard library, and is in fact an instance method of all Collection implementations.
There is no built-in all(), however. The closest you'll get, aside from your "sledgehammer" approach, is Google Guava's Iterables#all().
In Java 7 and earlier, there is nothing in the standard libraries for doing that.
In Java 8, you should be able to use Stream.allMatch(...) or Stream.anyMatch(...) for this kind of thing, though I'm not sure that this would be justifiable from a performance perspective. (For a start, you would need to use Boolean instead of boolean ...)
An example for Java 8 streaming API would be:
Boolean[] items = ...;
List<Boolean> itemsList = Arrays.asList(items);
if (itemsList.stream().allMatch(e -> e)) {
// all
}
if (itemsList.stream().anyMatch(e -> e)) {
// any
}
A solution with the third party library hamcrest:
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
if (everyItem(is(true)).matches(itemsList)) {
// all
}
if (hasItem(is(true)).matches(itemsList)) { // here is() can be omitted
// any
}