java 8 - how abstracts the use of predicates by using methods - java-8

I am trying to create a class that abstracts the use of predicates from its end user.
My app uses Guava-Retrying extension which works great.
Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
.retryIfResult(Predicates.<Boolean>isNull())
....
.build();
retryer.call(callable);
I can call easily call it with predicates and it polls until predicate returns false.
Now, maybe I misunderstand predicates but I am trying to create a class that will abstract them.
I wish to call it as follows
MyPoller.poll(new PollCondition<MyClass>() {
#Override public boolean condition() {
return !isValid(result**.getPermissions(), permissionName);
}
});
So I wrote PollCondition class as follows.
public abstract class PollCondition<T> {
public Predicate<T> getCondition() {
return result -> condition();
}
public abstract boolean condition();
}
but MyPoller.poll() call fail to compile - result is not declared.
Any idea?

It seems you don't understand predicates indeed. A predicate is a function that takes an input as argument, and returns a boolean value (usually based on the input, of course).
Let's examine your PollCondition class:
public abstract class PollCondition<T> {
public Predicate<T> getCondition() {
return result -> condition();
}
public abstract boolean condition();
}
So it defines an abstract condition() method that doesn't take anything as argument, and returns a boolean. And it can be "transformed" into a Predicate using getCondition(). This method returns a predicate which takes an input as argument (result), ignores it completely, and always returns the boolean returned by condition().
You then create a PollCondition using
new PollCondition<MyClass>() {
#Override public boolean condition() {
return !isValid(result.getPermissions(), permissionName);
}
}
That would be correct if, in the scope where you execute that code, there was a variable named result. But there is not. resultis in fact an input to your condition. So the class should in fact defined like this:
public abstract class PollCondition<T> {
public Predicate<T> getCondition() {
return result -> condition(result);
}
public abstract boolean condition(T result);
}
And you would then be able to instantiate one using
new PollCondition<MyClass>() {
#Override public boolean condition(MyClass result) {
return !isValid(result.getPermissions(), permissionName);
}
}
But I really, really don't see what that brings over using a simple Predicate directly.
Define MyPoller.poll() like this:
public poll(Predicate<T> predicate);
and use it like this:
MyPoller.poll(result -> !isValid(result.getPermissions(), permissionName));

Related

Spring's #Condtional annotation with Java 8

I was using #Conditional annotation and had to provide implementation of matches() of Condition interface. Since the Condition is a FunctionalInterface, how can I use Java 8 lambda to provide implementation in annotation rather than providing implementation.
#Conditional(value = MyCondition.class)
class MyCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return ifMatches;
}
}
You can't.
Lambdas are instances of classes and #Conditional needs the class itself.
The lambda
Function<String, String> capitalize = text -> text.substring(0, 1).toUpperCase() + text.substring(1).toLowerCase();
Is functionally identical to
Function<String, String> capitalize = new Function<String, String>() {
public String apply(String text) {
return Function<String, String> capitalize = text -> text.substring(0, 1).toUpperCase() + text.substring(1).toLowerCase();
}
};
Both are instances of anonymous classes and not the anonymous class itself. There is no way to actually access anonymous classes (outside of reflection, but you can't use reflection in annotations).
Passing a a lambda where a class is expected would be like passing a String where a class is expected. I.e. something like this:
public #interface MyAnnotation {
Class<?> value();
}
#MyAnnotation("this is a string")
public class MyClass {
}
which you wouldn't expect to work.

Lambda return type as generic [duplicate]

This question already has answers here:
Lambda Expression and generic defined only in method
(5 answers)
Closed 4 years ago.
Could someone help me how to write lambda implementation for the following functional interface.
public interface InnerLambda {
public <R> R test(String str);
}
And I have a class well
public class Example {
public static void main(String[] args) {
testInner(str->"");
}
public static void testInner(InnerLambda innerLambda){
}
}
You cannot use lambda expression for a functional interface with a generic method scoped.
Your interface functional would make more sense by being generic :
public interface InnerLambda<R> {
R test(String str);
}
Here are some examples.
To concatenate the String param to another String :
InnerLambda<String> l1 = s -> s + "other string";
To return a boolean according to the String param nullity :
InnerLambda<Boolean> l2 = Objects::nonNull;
It's good if you will have interface like this:
#FunctionalInterface // Ensure if your interface have only one bastract method.
public interface InnerLambda<R> {
public R test(String str);
}
There are many ways to do so one of them is given below:
InnerLamda innerLamda = str -> {
//implementation will go here.
// return the response
}
//You can call by using below line
int length = innerLamda.test("input");
Lamda will identify the value of R based of value you are returning
from your lamda.
Edit:
if you want to do it with generic at method level then you can do it with method references as it's not supported by lamda as stated in below document:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.3
method reference example is below:
//class_name::<type_here>method_name
lamdaFunctions::<String>process
Note: If you are calling it a functional interface then what is the
issue in defining the generic at the interface level.because there is
only one abstract method.

Sort a list of objects based on a parameterized attribute of the object

Assuming that we have an object with the following attributes:
public class MyObject {
private String attr1;
private Integer attr2;
//...
public String getAttr1() {
return this.attr1;
}
public Integer getAttr2() {
return this.attr2;
}
}
One way of sorting a list mylist of this object, based on its attribute attr1 is:
mylist.sort(Comparator.comparing(MyObject::getAttr1));
Is it possible to use this code inside a method in a dynamic way and replace the getAttr1 part with a method that returns the getter of an attribute of the object based on its name? Something like:
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(Comparator.comparing(MyObject::getGetterByAttr(attr)));
}
The MyObject::getGetterByAttr(attr) part does not compile, I wrote it just as an example to explain my idea
I tried to implement a method with the following code new PropertyDescriptor(attr, MyObject.class).getReadMethod().invoke(new MyObject()) but It's still not possible to call a method with a parameter from the comparing method
You could add a method like
public static Function<MyObject,Object> getGetterByAttr(String s) {
switch(s) {
case "attr1": return MyObject::getAttr1;
case "attr2": return MyObject::getAttr2;
}
throw new IllegalArgumentException(s);
}
to your class, but the returned function is not suitable for Comparator.comparing, as it expects a type fulfilling U extends Comparable<? super U> and while each of String and Integer is capable of fulfilling this constraint in an individual invocation, there is no way to declare a generic return type for getGetterByAttr to allow both type and be still compatible with the declaration of comparing.
An alternative would be a factory for complete Comparators.
public static Comparator<MyObject> getComparator(String s) {
switch(s) {
case "attr1": return Comparator.comparing(MyObject::getAttr1);
case "attr2": return Comparator.comparing(MyObject::getAttr2);
}
throw new IllegalArgumentException(s);
}
to be used like
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(getComparator(attr));
}
This has the advantage that it also may support properties whose type is not Comparable and requires a custom Comparator. Also, more efficient comparators for primitive types (e.g. using comparingInt) would be possible.
You may also consider using a Map instead of switch:
private static Map<String,Comparator<MyObject>> COMPARATORS;
static {
Map<String,Comparator<MyObject>> comparators=new HashMap<>();
comparators.put("attr1", Comparator.comparing(MyObject::getAttr1));
comparators.put("attr2", Comparator.comparing(MyObject::getAttr2));
COMPARATORS = Collections.unmodifiableMap(comparators);
}
public static Comparator<MyObject> getComparator(String s) {
Comparator<MyObject> comparator = COMPARATORS.get(s);
if(comparator != null) return comparator;
throw new IllegalArgumentException(s);
}
More dynamic is only possible via Reflection, but this would complicate the code, add a lot of potential error source, with only little benefit, considering that you need only to add one line of source code for adding support for another property in either of the examples above. After all, the set of defined properties gets fixed at compile time.
You could also have a single place where this comparators would be defined:
static enum MyObjectComparator {
ATTR1("attr1", Comparator.comparing(MyObject::getAttr1));
MyObjectComparator(String attrName, Comparator<MyObject> comparator) {
this.comparator = comparator;
this.attrName = attrName;
}
private final Comparator<MyObject> comparator;
private final String attrName;
private static MyObjectComparator[] allValues = MyObjectComparator.values();
public static Comparator<MyObject> findByValue(String value) {
return Arrays.stream(allValues)
.filter(x -> x.attrName.equalsIgnoreCase(value))
.map(x -> x.comparator)
.findAny()
.orElseThrow(RuntimeException::new);
}
}
And your usage would be:
public void sortListByAttr(List<MyObject> list, String attr) {
list.sort(MyObjectComparator.findByValue(attr));
}

Force boolean value in method call in JSP/EL

I have a JSP-Page which contains the following
<td>${MyClass.mymethod(false)}</td>
and MyClass contains the following:
public static String mymethod(boolean param)
{
//...
}
public static String mymethod(String param)
{
//...
}
Now when I display the JSP-Page mymethod(String param) is called. How can I make the false a boolean value?
Method names being put in a Map as keys.So there is no function overloading in el.or try giving different names for function in xml.

Guice : Injection and the compiler

If I declare a method :
public Car makeCar(#Named("carClassName") String carClassName){
//...
}
It seems that the compiler (eclipse) is unhappy (i.e. it won't let me call the class with no arguments).
How can I inject these parameters when I call this method , dynamically ? Is there a way to inject a call to a method ?
Solution 1: insert carClassName in the caller,
class Whatever {
private #Named("carClassName") String carClassName);
public void dosomething() {
...
Cat cat = makeCar(carclassName);
...
}
}
Solution 2: use a factory,
class CarFactory {
private #Named("carClassName") String carClassName);
public Car create() {
return makeCar(carClassName);
}
}
and inject it where needed.

Resources