Generic Filter for enum - java

Following is my class
public final class Test {
enum Animal {DOG,CAT};
enum COLOR {RED,YELLOW};
class Meaningless {
String animal,color;
}
public void filter(List<Meaningless> meaninglesses){
meaninglesses.stream()
.filter(meaningless -> {
try {
Animal.valueOf(meaningless.animal);
return true;
}catch(Exception e){
return false;
}
})
.filter(meaningless -> {
try {
COLOR.valueOf(meaningless.color);
return true;
}catch(Exception e){
return false;
}
})
.collect(Collectors.toList());
}
}
The 2 iterations of filter methods essentially filters out the invalid enum types. How can I remove the code duplication from this ? The check should be generic enough so that I dont have to change the isValidEnum when there is a new enum introduced.
Ideally I would like to do something like
meaninglesses.stream()
.filter(meaningless -> isValidEnum(meaningless.animal,Animal.class))
.filter(meaningless -> isValidEnum(meaningless.color,COLOR.class))

The following utility method should do the trick here,
public static <E extends Enum<E>> boolean validateEnum(Class<E> clazz, String s) {
return EnumSet.allOf(clazz).stream().anyMatch(e -> e.name().equals(s));
}
And here's how your client code looks in practice,
boolean isValid = validateEnum(Animal.class, "DOG");
Finally, putting it back to your context, it should be something like this.
meaninglesses.stream()
.filter(meaningless -> validateEnum(Animal.class, meaningless.animal))
.filter(meaningless -> validateEnum(COLOR.class, meaningless.color))
.collect(Collectors.toList());

Instead of reinventing the wheel, you can simply go with Apache Common EnumUtils isValidEnum(Class<E> enumClass,String enumName)
Also, isValidEnumIgnoreCase(Class<E> enumClass,String enumName) can be used to check if you need case-insensitivity.
Docs here

Related

How to implement BiFunctional function that corresponds to Enum in Java?

I have Java enum:
public enum ConflictResolutionStrategy {
softResolve,
hardResolve,
}
I want to call it like ConflictResolutionStrategy.hardResolve.apply(case1, case2).
Both case1 and case2 objects of the same type. apply in my case should return nothing.
The basic idea behind this design. Create Strategy design pattern and resolve conflicts based on the set enum value.
I cannot find any similar questions on StackOveflow even simple search gives me tons of similar cases which don't resolve my case directly.
I tried The following:
public enum ConflictResolutionStrategy {
softResolve ((CaseType case1, CaseType case2) -> case1.update(case2)),
hardResolve,
}
This version above doesn't compile.
I tried another solution:
public enum ConflictResolutionStrategy {
softResolve,
hardResolve {
public void apply(CaseType case1, CaseType case2) {
case1.update(case2);
}
},
}
The second solution, works okay but requires too much code.
A function accepting two parameters and returning nothing is a BiConsumer.
Your enum may implement BiConsumer:
public enum ConflictResolutionStrategy implements BiConsumer<CaseType, CaseType> {
softResolve ((case1, case2) -> case1.update(case2)),
hardResolve((case1, case2) -> {/* do something else */});
private final BiConsumer<CaseType, CaseType> consumer;
ConflictResolutionStrategy(BiConsumer<CaseType, CaseType> consumer){
this.consumer = consumer;
}
#Override
public void accept(CaseType case1, CaseType case2) {
consumer.accept(case1, case2);
}
}
Suppose you have a method for processing your cases:
public void processCases(Collection<CaseType> cases, BiConsumer<CaseType, CaseType> conflictResolutionStrategy){
// ...
}
Now you can pass in either one of your existing strategies:
processCases(cases, ConflictResolutionStrategy.softResolve);
or an inline strategy:
processCases(cases, (c1, c2) -> { /* do smth here */ });
Maybe you're looking for something like a BiConsumer within the enum as :
public enum ConflictResolutionStrategy {
softResolve(CaseType::update), // just for example
hardResolve((caseType, caseType2) -> {
caseType.update(caseType2);
}); // lambda representation
BiConsumer<CaseType, CaseType> caseTypeBiConsumer;
ConflictResolutionStrategy(BiConsumer<CaseType, CaseType> caseTypeBiConsumer) {
this.caseTypeBiConsumer = caseTypeBiConsumer;
}
}
class CaseType {
void update(CaseType caseType){}
}

function name as a string

I am trying to wrap my head around generic and functions... what I am trying to achieve: Passing function name as a string to get it executed:
I want to do Wrapper.useFunction("eleven") or Wrapper.useFunction("ten")
public class Wrapper<T> {
public F useFunction(Function<F, F> function) {
return function.apply(F);
}
Function<F, String> ten = s -> "10";
Function<F, String> eleven = s -> "11";
}
But this code not even close to compiling. Maybe it doesn't make any sense. Any suggestions?
If you have a finite set of functions which you would like to be able to call I would recommend building a Map which maps Strings to instances of Runnable (or similar functional interfaces). Your useFunction method may then look up the function implementation in the Map and call it if it exists.
Example:
public class SomeClass {
private final Map<String, Runnable> methods = new HashMap<>();
{
methods.put("helloworld", () -> {
System.out.println("Hello World!");
});
methods.put("test", () -> {
System.out.println("test!");
});
methods.put("doStuff", () -> {
System.out.println("doStuff!");
});
}
public void perform(String code) {
methods.getOrDefault(code,
() -> {
System.err.println("No such Method: "+code);
})
.run();
}
}
If you want to call arbitrary methods you should probably use Reflection as stated by others.

How can we pass a variable field /method name in Comparator.comparing

I have a Report {String name, Date date, int score } class.
I want to be able to sort a list of reports for any member variable using the new java 8 syntax
So java 8 provides this new
list.sort(Comparator.comparing(report -> report.name))
to sort the list on name.
Lets say instead of name I want to provide a variable field name to this method eg. something like
list.sort(Comparator.comparing(report -> report.anyField))
where anyField can be name or date or score. How do I achieve this behavior.
Just create a comparator for each property.
static Map<String,Comparator<Report>> ORDER;
static {
HashMap<String,Comparator<Report>> m=new HashMap<>();
m.put("name", Comparator.comparing(r -> r.name));
m.put("date", Comparator.comparing(r -> r.date));
m.put("score", Comparator.comparingInt(r -> r.score));
ORDER=Collections.unmodifiableMap(m);
}
public static void sort(List<Report> list, String order) {
Comparator<Report> c=ORDER.get(order);
if(c==null) throw new IllegalArgumentException(order);
list.sort(c);
}
You may consider using an enum as alternative to String, which eliminates the possibility of providing a non-existent property name:
enum ReportOrder {
NAME(Comparator.comparing(r -> r.name)),
DATE(Comparator.comparing(r -> r.date)),
SCORE(Comparator.comparingInt(r -> r.score));
private Comparator<Report> cmp;
private ReportOrder(Comparator<Report> c) { cmp=c; }
public void sort(List<Report> list) {
list.sort(cmp);
}
}
Now you can just say, e.g. ReportOrder.NAME.sort(list);. Of course, the other delegation style works as well:
public static void sort(List<Report> list, ReportOrder o) {
list.sort(o.cmp);
}
 
sort(list, ReportOrder.DATE);
One very generic solution is to use Java's Reflection and some casting:
String sortBy = "name";
list.sort(Comparator.comparing(report -> {
try {
return (Comparable) report.getClass().getDeclaredField(sortBy).get(report);
} catch (Exception e) {
throw new RuntimeException("Ooops", e);
}
}));
If you use an additional library like https://github.com/jOOQ/jOOR the code becomes even simpler:
String sortBy = "score";
list.sort(Comparator.comparing(report -> Reflect.on(report).field(sortBy).get()));
Please be aware that this solution only works with fields that implement Comparable and that it has some runtime overhead.
public class Report {
//properties and getters
public static void sort(List<Report> list, Function<Report, Comparable> sortKey) {
list.sort(Comparator.comparing(sortKey));
}
}
Report.sort(reports, Report::getName);
Report.sort(reports, Report::getDate);
Report.sort(reports, Report::getScore);
Could make this into a generic util class where you can pass in a List of any class:
public class MyUtil<T> {
void sort(List<T> t, Function<T, Comparable> sortKey) {
t.sort(Comparator.comparing(sortKey));
}
}
MyUtil<Report> util = new MyUtil();
util.sort(ppl, Report::getName);
If your Report has getter method of various field you can do like this
list.sort(Comparator.comparing(Report::getFieldName));
Or with lambda expression
list.sort((ob1, ob2) -> ob1.getFieldName().compareTo(ob2.getFieldName()));
At some place, you'll have to use a bit of reflection to pull this off. Here's an example using the bean introspection mechanism of java:
public static class MyBean {
private String name;
private Date birthday;
private Integer score;
...
... (constructor, getters, setters - the usual bean stuff)
}
PropertyDescriptor[] pdesc = Introspector.getBeanInfo(MyBean.class).getPropertyDescriptors();
for(PropertyDescriptor pd : pdesc) {
if(Comparable.class.isAssignableFrom(pd.getPropertyType())) {
System.out.println("Property " + pd.getName() + " could be used for comparison");
Function<MyBean, Comparable> extractor = b -> {
try {
return (Comparable) pd.getReadMethod().invoke(b);
}
catch(Exception e) {
throw new RuntimeException(e);
}
};
Comparator<MyBean> comp = Comparator.comparing(extractor);
// do something useful with the comparator :-)
}
}
Additionally, you could go a similar way for primitive types (e.g. int, which does not implement Comparable as opposed to Integer.)
If the set of properties is fixed (name, date, score) then I think a clean way would be to pass a Comparator:
private void someMethod(Comparator<Report> comparator){
...
list.sort(comparator);
...
}
...
someMethod(Comparator.comparing(report::getName));
someMethod(Comparator.comparing(report::getDate));
someMethod(Comparator.comparingInt(report::getScore));
someMethod(Comparator.comparing(report::getName).thenComparingInt(report::getScore));
There is a Comparator class called NamedMethodComparator that will work as a Comparator for any zero arg method that returns a Comparable posted here: How to use Comparator in Java to sort

Java Optionals - how to write in functional style? [duplicate]

I want to replace the following code using java8 Optional:
public Obj getObjectFromDB() {
Obj obj = dao.find();
if (obj != null) {
obj.setAvailable(true);
} else {
logger.fatal("Object not available");
}
return obj;
}
The following pseudocode does not work as there is no orElseRun method, but anyways it illustrates my purpose:
public Optional<Obj> getObjectFromDB() {
Optional<Obj> obj = dao.find();
return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}
With Java 9 or higher, ifPresentOrElse is most likely what you want:
Optional<> opt = dao.find();
opt.ifPresentOrElse(obj -> obj.setAvailable(true),
() -> logger.error("…"));
Currying using vavr or alike might get even neater code, but I haven't tried yet.
I don't think you can do it in a single statement. Better do:
if (!obj.isPresent()) {
logger.fatal(...);
} else {
obj.get().setAvailable(true);
}
return obj;
For Java 8 Spring Data offers ifPresentOrElse from "Utility methods to work with Optionals" to achieve what you want.
Example would be:
import static org.springframework.data.util.Optionals.ifPresentOrElse;
ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));
You will have to split this into multiple statements. Here is one way to do that:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
obj.ifPresent(o -> o.setAvailable(true));
return obj;
Another way (possibly over-engineered) is to use map:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> {o.setAvailable(true); return o;});
If obj.setAvailable conveniently returns obj, then you can simply the second example to:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> o.setAvailable(true));
There is an .orElseRun method, but it is called .orElseGet.
The main problem with your pseudocode is that .isPresent doesn't return an Optional<>. But .map returns an Optional<> which has the orElseGet method.
If you really want to do this in one statement this is possible:
public Optional<Obj> getObjectFromDB() {
return dao.find()
.map( obj -> {
obj.setAvailable(true);
return Optional.of(obj);
})
.orElseGet( () -> {
logger.fatal("Object not available");
return Optional.empty();
});
}
But this is even clunkier than what you had before.
First of all, your dao.find() should either return an Optional<Obj> or you will have to create one.
e.g.
Optional<Obj> = dao.find();
or you can do it yourself like:
Optional<Obj> = Optional.ofNullable(dao.find());
this one will return Optional<Obj> if present or Optional.empty() if not present.
So now let's get to the solution,
public Obj getObjectFromDB() {
return Optional.ofNullable(dao.find()).flatMap(ob -> {
ob.setAvailable(true);
return Optional.of(ob);
}).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});
}
This is the one liner you're looking for :)
For those of you who want to execute a side-effect only if an optional is absent
i.e. an equivalent of ifAbsent() or ifNotPresent() here is a slight modification to the great answers already provided.
myOptional.ifPresentOrElse(x -> {}, () -> {
// logic goes here
})
Title: "How to execute logic on Optional if not present?"
Answer:
Use orElseGet() as a workaround for the missing ifNotPresent(). And since it expects us to return something just return
null.
Optional.empty().orElseGet(() -> {
System.out.println("The object is not present");
return null;
});
//output: The object is not present
or
Optional.ofNullable(null).orElseGet(() -> {
System.out.println("The object is not present");
return null;
});
//output: The object is not present
I also use it to easily implement the singleton pattern with lazy initialization.
public class Settings {
private Settings(){}
private static Settings instance;
public static synchronized Settings getInstance(){
Optional.ofNullable(instance).orElseGet(() -> instance = new Settings());
return instance;
}
}
Of course the getInstance() content can be written in one line by directly returning the first statement, but I wanted to demonstrate the use of orElseGet() as an ifNotPresent().
I was able to came up with a couple of "one line" solutions, for example:
obj.map(o -> (Runnable) () -> o.setAvailable(true))
.orElse(() -> logger.fatal("Object not available"))
.run();
or
obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true))
.orElse(o -> logger.fatal("Object not available"))
.accept(null);
or
obj.map(o -> (Supplier<Object>) () -> {
o.setAvailable(true);
return null;
}).orElse(() () -> {
logger.fatal("Object not available")
return null;
}).get();
It doesn't look very nice, something like orElseRun would be much better, but I think that option with Runnable is acceptable if you really want one line solution.
With Java 8 Optional it can be done with:
Optional<Obj> obj = dao.find();
obj.map(obj.setAvailable(true)).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});
In order to get the value from one call, or do an extra call if the previous returned an empty value, you can chain the commands.
public Optional<Obj> getObjectFromDB() {
return dao.find().or(() -> dao.findBySomethingElse());
}
You need Optional.isPresent() and orElse(). Your snippet won;t work because it doesn't return anything if not present.
The point of Optional is to return it from the method.
ifPresentOrElse can handle cases of nullpointers as well. Easy approach.
Optional.ofNullable(null)
.ifPresentOrElse(name -> System.out.println("my name is "+ name),
()->System.out.println("no name or was a null pointer"));
I suppose you cannot change the dao.find() method to return an instance of Optional<Obj>, so you have to create the appropriate one yourself.
The following code should help you out. I've create the class OptionalAction,
which provides the if-else mechanism for you.
public class OptionalTest
{
public static Optional<DbObject> getObjectFromDb()
{
// doa.find()
DbObject v = find();
// create appropriate Optional
Optional<DbObject> object = Optional.ofNullable(v);
// #formatter:off
OptionalAction.
ifPresent(object)
.then(o -> o.setAvailable(true))
.elseDo(o -> System.out.println("Fatal! Object not available!"));
// #formatter:on
return object;
}
public static void main(String[] args)
{
Optional<DbObject> object = getObjectFromDb();
if (object.isPresent())
System.out.println(object.get());
else
System.out.println("There is no object!");
}
// find may return null
public static DbObject find()
{
return (Math.random() > 0.5) ? null : new DbObject();
}
static class DbObject
{
private boolean available = false;
public boolean isAvailable()
{
return available;
}
public void setAvailable(boolean available)
{
this.available = available;
}
#Override
public String toString()
{
return "DbObject [available=" + available + "]";
}
}
static class OptionalAction
{
public static <T> IfAction<T> ifPresent(Optional<T> optional)
{
return new IfAction<>(optional);
}
private static class IfAction<T>
{
private final Optional<T> optional;
public IfAction(Optional<T> optional)
{
this.optional = optional;
}
public ElseAction<T> then(Consumer<? super T> consumer)
{
if (optional.isPresent())
consumer.accept(optional.get());
return new ElseAction<>(optional);
}
}
private static class ElseAction<T>
{
private final Optional<T> optional;
public ElseAction(Optional<T> optional)
{
this.optional = optional;
}
public void elseDo(Consumer<? super T> consumer)
{
if (!optional.isPresent())
consumer.accept(null);
}
}
}
}

Mapping a Nested Optional?

I'm kind of running into a tedious issue with the Java 8 "Optional" container. I cannot map an Optional to "bubble up" another optional.
Let's say I have a RussianNestingDoll class
public class NestedOptionalTest {
public static void main(String[] args) {
RussianNestingDoll doll = RussianNestingDoll.createInstance(RussianNestingDoll.createInstance(RussianNestingDoll.createInstance()));
Optional<Optional<RussianNestingDoll>> thirdDollContents = doll.getInnerDoll().map(d -> d.getInnerDoll());
if (thirdDollContents.isPresent() && thirdDollContents.get().isPresent()) {
System.out.println(thirdDollContents.get().get());
}
else {
System.out.println("empty");
}
}
private static final class RussianNestingDoll {
private final Optional<RussianNestingDoll> innerDoll;
public Optional<RussianNestingDoll> getInnerDoll() {
return innerDoll;
}
private RussianNestingDoll(Optional<RussianNestingDoll> innerDoll) {
this.innerDoll = innerDoll;
}
public static RussianNestingDoll createInstance() {
return new RussianNestingDoll(Optional.empty());
}
public static RussianNestingDoll createInstance(RussianNestingDoll innerDoll) {
return new RussianNestingDoll(Optional.of(innerDoll));
}
}
}
It would be nice to not have to use nested optionals, and instead just have the optional "bubble up". That way I can call "isPresent()" and "get()" just once, rather than calling them both twice. Is there a way I can accomplish this?
I'm not really sure what you want, but you can rewrite your code like this:
RussianNestingDoll doll = RussianNestingDoll.get(RussianNestingDoll.get(RussianNestingDoll.get()));
String content = doll.getInnerDoll()
.flatMap(d -> d.getInnerDoll())
.map(d -> d.get().toString())
.orElse("empty");
System.out.println(content);
In case you want to use the doll afterwards:
Optional<RussianNestingDoll> thirdDoll = doll.getInnerDoll()
.flatMap(d -> d.getInnerDoll());
if (thirdDoll.isPresent()) {
System.out.println(thirdDoll.get());
}
else {
System.out.println("empty");
}
Do you want to flatMap?
thirdDollContents
.flatMap(Function.identity()) // un-nest, get back an Optional<RussianNestingDoll>
.get() // or isPresent()
The flatMap will return an empty Optional if thirdDollContents is empty.

Categories