Java equivalent to python all and any - java

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
}

Related

How to set a value to variable based on multiple conditions using Java Streams API?

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;
}

Extract all True properties and add to a list

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?

Analog of everyItem() from Hamcrest in AssertJ

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();

If not null - java 8 style

Java 8 presents Optional class.
Before (Java 7):
Order order = orderBean.getOrder(id);
if (order != null) {
order.setStatus(true);
pm.persist(order);
} else {
logger.warning("Order is null");
}
So on Java 8 style:
Optional<Order> optional = Optional.ofNullable(orderBean.getOrder(id));
optional.ifPresent( s -> {
s.setStatus(true);
pm.persist(s);
//Can we return from method in this place (not from lambda) ???
});
//So if return take place above, we can avoid if (!optional.isPresent) check
if (!optional.isPresent) {
logger.warning("Order is null");
}
Is it correct to use Optional in this case? Can anyone propose a more convenient way in Java 8 style?
Unfortunately, the ifPresentOrElse method you're looking for will be added only in JDK-9. Currently you can write your own static method in your project:
public static <T> void ifPresentOrElse(Optional<T> optional,
Consumer<? super T> action, Runnable emptyAction) {
if (optional.isPresent()) {
action.accept(optional.get());
} else {
emptyAction.run();
}
}
And use like this:
Optional<Order> optional = Optional.ofNullable(orderBean.getOrder(id));
ifPresentOrElse(optional, s -> {
s.setStatus(true);
pm.persist(s);
}, () -> logger.warning("Order is null"));
In Java-9 it would be easier:
optional.ifPresentOrElse(s -> {
s.setStatus(true);
pm.persist(s);
}, () -> logger.warning("Order is null"));
//Can we return from method in this plase (not from lambda) ???
Lambdas do not implement "non-local return" semantics, therefore the answer is no.
Generally, since you need side-effectful action in both the case where the value is present and not, a branching point in the code is essential—whether you wrap it in some fancy API or not. Also, FP generally helps improve referentially transparent transformations (i.e., code built around pure functions) and not side effects, so you won't find much benefit by going through the Optional API.

Java inline predicates: cannot be resolved to a variable

Sorry for the simple question - I come from the .NET stack. All I want is an inline Predicate. Please tell me what I'm doing wrong:
toReturn = Iterables.find(articles, a -> a.toString().equals(input));
It tells me that 'a cannot be resolved to a variable'. I'm assuming that I just need an import or that I'm using an old version of Java? Thanks in advance!
What you're trying to do is not possible in Java 7 or earlier; it exists in Java 8 and later though. With Java 7 and prior you are able to use lambdaj to similar effect though. It would look something like this:
toReturn = Iterables.find(articles, new Predicate<Object>() {
public boolean apply(Object item) {
return item.toString().equals(input);
}
});
You can check out more details here.
Edit:
As pointed out in the comments, there are alternatives. As you're using Iterables I'm guessing you would want a com.google.common.base.Predicate which can be defined very similarly:
toReturn = Iterables.find(articles, new Predicate<Object>() {
public boolean apply(Object item) {
return item.toString().equals(input);
}
public boolean equals(Object obj) {
// check whether the other object is also a Predicate
}
});

Categories

Resources