Common generic method to handle operations on subclasses of java.lang.Number - java

I have a class MyGen which takes two generic arguments and has a method getValue()
public interface MyGen<E,T> {
T getValue();
}
Usually the second generic type would be either Long or Integer.
Then, I wrote a method to combine the objects when the second generic type is Long as below:
public static <E extends MyGen<?, Long>> long combineValue(Set<E> set) {
return set.stream()
.map(MyGen::getValue)
.reduce(0L, (a,b) -> a | b);
}
Now I want to have a similar method when the second type is an Integer. So I tried updating the above same method to :
public static <E extends MyGen<?, ? extends Number>> long combineValue(Set<E> set) {
return (long) set.stream()
.map(MyGen::getValue)
.reduce((a,b) -> a | b) // error1
.orElse(0); // error2
}
But the following errors are displayed:
error1
The operator | is undefined for the argument type(s) capture#4-of ?
extends java.lang.Number, capture#4-of ? extends java.lang.Number
error2
The method orElse(capture#4-of ? extends Number) in the type
Optional<capture#4-of ? extends Number> is not applicable for the
arguments (int)
Is there any way to handle both Long and Integer in the same method or could it be done only using two separate methods?

You seem to be fine about the return value of this common method being long. In that case, it is possible, because you can get a long from a Number using longValue:
public static long combineValue(Set<? extends MyGen<?, ? extends Number>> set) {
return set.stream()
.map(MyGen::getValue)
.mapToLong(Number::longValue)
.reduce(0L, (a,b) -> a | b);
}
You basically turn every number into longs first, and then do the reduction.

Related

Explanation for v-> v>5

I have a given function call and java gives me an error because Objects are not comparable to ints (of course...). Can someone explain to me what I have to change?
I tried to brace the lambda expression differently but with no useful result. I think, that the lambda expression is correct and the filter-function is slightly wrong, but I'm not able to find out my mistake...
// function call
filter(v -> v > 5)
// function
public Optional<T> filter(Predicate<T> tester) {
if(isPresent() && tester.test(get())) {
return this;
} else {
return Optional.empty();
}
}
I would expect a Optional.empty-Object but I get a java-error because v > 5 Object v is not comparable to an int.
You have to make T a wrapper class which is comparable with an int. e.g.
IntStream.range(0, 10)
.filter(v -> v > 5)
.forEach(System.out::println);
is fine because v is an int.
You can't use this expression when T is unknown.
What you can do is assume the T must be a number e.g.
filter( v -> ((Number) v).doubleValue() > 5)
however this will produce a ClassCastExpection is T is another type.
The real solution is to make T a Number
e.g.
class MyClass<T extends Number> {
public Optional<T> filter(Predicate<T> test) {
or make it a specific type like int
class MyClass {
public IntOptional filter(IntPredicate test) {
In Java primitives types (e.g. int) and objects (e.g. Object) don't have a common ancestor in the type hierarchy. Due to that predicates and other stream constructs come in two flavors e.g. there is IntPredicate that you have to use when working with int and Predicate that you have to use when working with Object.
On way to write your filter function would be to use OptionalInt and IntPredicate:
public OptionalInt filter(IntPredicate tester) {
if (isPresent() && tester.test(get())) {
return ...
} else {
return OptionalInt.empty();
}
}
v -> v > 5 can mean different things. It depends on context.
It could be a (Object v) -> v > 5 causing a compilation error since > can't be applied to an Object:
Stream.<Object>of("123", 123).filter(v -> v > 5);
It could be a (Integer v) -> v > 5 meaning that unboxing and autoboxing will be performed in order to do the comparison and to return the result:
Stream.<Integer>of(123, 123).filter(v -> v > 5);
It could be a (int v) -> v > 5 meaning that it's an instance of IntPredicate and things will go smoothly here:
IntStream.of(123, 123).filter(v -> v > 5);
I think, that the lambda expression is correct and the
filter-function is slightly wrong, but I'm not able to find out my
mistake...
You are right.
Your method seems to defeat the generic type declared for the class as first of all your method is defined inside a generic class.
Supposing your class is named Foo, here the filter() method relies on the generic T type as return/parameter type :
public class Foo<T>{
// ...
public Optional<T> filter(Predicate<T> tester) {
// ...
}
}
It works with inference.
So you get Predicate of T. But the T depends on the generic type defined in the class and also from the way which you declared the instance of the Foo class.
And it appears that here T is not a Number.
As alternative you could also rely on inference from the declared Foo variable.
If you do that :
Foo<Integer> foo = new Foo<>();
Optional<Integer> optInt = foo.filter(v -> v > 5);
it will compile fine as Integer will be inferred from Foo<Integer>.
So I think that to solve your issue, you should either declare Number or Integer as base class of the generic type :
public class Foo<T extends Integer>{
// ...
public Optional<T> filter(Predicate<T> tester) {
// ...
}
}
or rely on the inference of the client as in the previous example.

Java 8 Comparator comparing static function

For the comparing source code in Comparator class
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
I understand the difference between super and extends. What i dont understand is that why this method have them. Can someone give me an example on what cannot be achieved when the parameter look like this Function<T, U> keyExtractor ?
For example :
Comparator<Employee> employeeNameComparator = Comparator.comparing(Employee::getName);
can also compile with the following function definition
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<T, U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
Here is a simple example: comparing cars by weight. I will first describe the problem in text-form, and then demonstrate every possible way how it can go wrong if either ? extends or ? super is omitted. I also show the ugly partial workarounds that are available in every case. If you prefer code over prose, skip directly to the second part, it should be self-explanatory.
Informal discussion of the problem
First, the contravariant ? super T.
Suppose that you have two classes Car and PhysicalObject such that Car extends PhysicalObject. Now suppose that you have a function Weight that extends Function<PhysicalObject, Double>.
If the declaration were Function<T,U>, then you couldn't reuse the function Weight extends Function<PhysicalObject, Double> to compare two cars, because Function<PhysicalObject, Double> would not conform to Function<Car, Double>. But you obviously want to be able to compare cars by their weight. Therefore, the contravariant ? super T makes sense, so that Function<PhysicalObject, Double> conforms to Function<? super Car, Double>.
Now the covariant ? extends U declaration.
Suppose that you have two classes Real and PositiveReal such that PositiveReal extends Real, and furthermore assume that Real is Comparable.
Suppose that your function Weight from the previous example actually has a slightly more precise type Weight extends Function<PhysicalObject, PositiveReal>. If the declaration of keyExtractor were Function<? super T, U> instead of Function<? super T, ? extends U>, you wouldn't be able to make use of the fact that PositiveReal is also a Real, and therefore two PositiveReals couldn't be compared with each other, even though they implement Comparable<Real>, without the unnecessary restriction Comparable<PositiveReal>.
To summarize: with the declaration Function<? super T, ? extends U>, the Weight extends Function<PhysicalObject, PositiveReal> can be substituted for a Function<? super Car, ? extends Real> to compare Cars using the Comparable<Real>.
I hope this simple example clarifies why such a declaration is useful.
Code: Full enumeration of the consequences when either ? extends or ? super is omitted
Here is a compilable example with a systematic enumeration of all things that can possibly go wrong if we omit either ? super or ? extends. Also, two (ugly) partial work-arounds are shown.
import java.util.function.Function;
import java.util.Comparator;
class HypotheticComparators {
public static <A, B> Comparator<A> badCompare1(Function<A, B> f, Comparator<B> cb) {
return (A a1, A a2) -> cb.compare(f.apply(a1), f.apply(a2));
}
public static <A, B> Comparator<A> badCompare2(Function<? super A, B> f, Comparator<B> cb) {
return (A a1, A a2) -> cb.compare(f.apply(a1), f.apply(a2));
}
public static <A, B> Comparator<A> badCompare3(Function<A, ? extends B> f, Comparator<B> cb) {
return (A a1, A a2) -> cb.compare(f.apply(a1), f.apply(a2));
}
public static <A, B> Comparator<A> goodCompare(Function<? super A, ? extends B> f, Comparator<B> cb) {
return (A a1, A a2) -> cb.compare(f.apply(a1), f.apply(a2));
}
public static void main(String[] args) {
class PhysicalObject { double weight; }
class Car extends PhysicalObject {}
class Real {
private final double value;
Real(double r) {
this.value = r;
}
double getValue() {
return value;
}
}
class PositiveReal extends Real {
PositiveReal(double r) {
super(r);
assert(r > 0.0);
}
}
Comparator<Real> realComparator = (Real r1, Real r2) -> {
double v1 = r1.getValue();
double v2 = r2.getValue();
return v1 < v2 ? 1 : v1 > v2 ? -1 : 0;
};
Function<PhysicalObject, PositiveReal> weight = p -> new PositiveReal(p.weight);
// bad "weight"-function that cannot guarantee that the outputs
// are positive
Function<PhysicalObject, Real> surrealWeight = p -> new Real(p.weight);
// bad weight function that works only on cars
// Note: the implementation contains nothing car-specific,
// it would be the same for every other physical object!
// That means: code duplication!
Function<Car, PositiveReal> carWeight = p -> new PositiveReal(p.weight);
// Example 1
// badCompare1(weight, realComparator); // doesn't compile
//
// type error:
// required: Function<A,B>,Comparator<B>
// found: Function<PhysicalObject,PositiveReal>,Comparator<Real>
// Example 2.1
// Comparator<Car> c2 = badCompare2(weight, realComparator); // doesn't compile
//
// type error:
// required: Function<? super A,B>,Comparator<B>
// found: Function<PhysicalObject,PositiveReal>,Comparator<Real>
// Example 2.2
// This compiles, but for this to work, we had to loosen the output
// type of `weight` to a non-necessarily-positive real number
Comparator<Car> c2_2 = badCompare2(surrealWeight, realComparator);
// Example 3.1
// This doesn't compile, because `Car` is not *exactly* a `PhysicalObject`:
// Comparator<Car> c3_1 = badCompare3(weight, realComparator);
//
// incompatible types: inferred type does not conform to equality constraint(s)
// inferred: Car
// equality constraints(s): Car,PhysicalObject
// Example 3.2
// This works, but with a bad code-duplicated `carWeight` instead of `weight`
Comparator<Car> c3_2 = badCompare3(carWeight, realComparator);
// Example 4
// That's how it's supposed to work: compare cars by their weights. Done!
Comparator<Car> goodComparator = goodCompare(weight, realComparator);
}
}
Related links
Detailed illustration of definition-site covariance and contravariance in Scala: How to check covariant and contravariant position of an element in the function?
Let's say, for example, we want to compare commercial flights by what plane they use. We would therefore need a method that takes in a flight, and returns a plane:
Plane func (CommercialFlight)
That is, of course, a Function<CommercialFlight, Plane>.
Now, the important thing is that the function returns a Plane. It doesn't matter what kind of plane is returned. So a method like this should also work:
CivilianPlane func (CommercialFlight)
Now technically this is a Function<CommercialFlight, CivilianPlane>, which is not the same as a Function<CommercialFlight, Plane>. So without theextends`, this function wouldn't be allowed.
Similarly, the other important thing is that is can accept a CommercialFlight as an argument. So a method like this should also work:
Plane func (Flight)
Technically, this is a Function<Flight, Plane>, which is also not the same as a Function<CommercialFlight, Plane>. So without the super, this function wouldn't be allowed either.

Java Lambda to comparator conversion - intermediate representation

I'm trying to make sense of how Comparator.comparing function works. I created my own comparing method to understand it.
private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
BiFunction<T,T,Integer> bfun = (T a, T b) -> f.apply(a).compareTo(f.apply(b));
return (Comparator<T>) bfun;
}
The last line in this function throws an exception.
However, if I change this function to
private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
return (T a, T b) -> f.apply(a).compareTo(f.apply(b));
}
It works just fine as expected.
What is the intermediate functional interface which the second attempt uses, which is able to convert the lambda to Comparator?
What is the intermediate functional interface which the second attempt uses, which is able to convert the lambda to Comparator?
The Comparator itself.
Within the second method, you have defined a Comparator, not an intermediate object that has been cast to the Comparator.
The last line in this function throws an exception.
Yes, it should.
If two classes are functional interfaces and have similar methods (with the identical signatures and the same return type), it doesn't mean that they can be used interchangeably.
An interesting trick - you may make a Comparator<T> by referring to the BiFunction<T, T, Integer> bfun's method apply:
private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
final BiFunction<T,T,Integer> bfun = (T a, T b) -> f.apply(a).compareTo(f.apply(b));
return bfun::apply; // (a, b) -> bfun.apply(a, b);
}
The intermediate functional interface in your second attempt is simply Comparator<T>:
You can see this because your code-snippet is equivalent to the following:
private static <T,U extends Comparable<U>> Comparator<T> comparing(Function<T,U> f) {
Comparator<T> comparator = (T a, T b) -> f.apply(a).compareTo(f.apply(b));
return comparator;
}

How generics really works as in parameters?

I'm little confused about how the generics works? I'm learning about function API in java and there I just test Function interface and got confused about compose method that how the generics is working in compose method.
Reading the generics on the java official tutorial website I realize that if we have any generic type in the method return or parameters we have to declare that type in the signature of method as explained below.
Here is the method I read in official docs tutorial.
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
Above method have two types, K, V which are declared in the signature after the static keyword as but when I read java Function API there is one method called compose and the signature of the compose is as
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
1) The first question where is the T & R declared? which are being used in the return type and in the parameter. Or my understanding is wrong?
Then I read more in generics tutorials and then I try to understand the concept of super and extends in generics and read here then I test compose method more and then confused again about how the super and extends works in the compose method?
public static void main(String... args){
Function<Integer, String> one = (i) -> i.toString();
Function<String, Integer> two = (i) -> Integer.parseInt(i);
one.compose(two);
}
As above I have declared two Function with lamdas. One is having Integer input and String output the other one is reversed from it.
2) The second question is that how Integer and String are related to extends and super? There is no relation between String and Integer class no one is extending each other then how it is working?
I tried my best to explain my question/problem. Let me know what you didn't understand I will try again.
Where are T and R defined?
Remember, compose is declared in the Function interface. It can not only use generic parameters of its own, but also the type's generic parameters. R and T are declared in the interface declaration:
interface Function<T, R> {
...
}
What are ? extends and ? super?
? is wildcard. It means that the generic parameter can be anything. extends and super give constraints to the wildcard. ? super V means that whatever ? is, it must be a superclass of V or V itself. ? extends T means that whatever ? is, it must be a subclass of T or T itself.
Now let's look at this:
Function<Integer, String> one = (i) -> i.toString();
Function<String, Integer> two = (i) -> Integer.parseInt(i);
one.compose(two);
From this, we can deduce that T is Integer and R is String. What is V? V must be some type such that the constraints Function<? super V, ? extends T> is satisfied.
We can do this by substituting the argument we passed in - Function<String, Integer> - to get String super V and Integer extends Integer.
The second constraint is satisfied already while the first constraint now says that String must be a super class of V or String itself. String cannot have subclasses so V must be String.
Hence, you can write something like:
Function<String, String> f = one.compose(two);
but not
Function<Integer, String> f = one.compose(two);
When you compose a Function<Integer, String> and a Function<String, Integer> you cannot possibly get a Function<Integer, String>. If you try to do this, V is automatically inferred to be Integer. But String super Integer is not satisfied, so the compilation fails. See the use of the constraints now? It is to avoid programmers writing things that don't make sense. Another use of the constraints is to allow you to do something like this:
Function<A, B> one = ...
Function<C, SubclassOfB> two = ...
Function<SubclassOfC, B> f = one.compose(two);
There is no relationship between Integer and String in this case, it's all about V.
1) The compose function is part of Interface Function<T,R>. As you can see in documentation for this interface:
Type Parameters:
T - the type of the input to the function
R - the type of the result of the function
2) The super and extends constraints in questions aren't applied to T & R, they're applied to the generic type parameters of a function that you pass in as an argument to the compose function.
Basically this means that if you have:
Function<ClassA, ClassB> one;
Function<SomeSuperClassOfC, SomeSubclassOfA> two;
then it's valid to call
Function<ClassC, ClassB> three = one.compose(two)
I will try to explain from zero;
interface Function<T, R> - this is interface with one method, which must be implemented R apply (T);
in Java prior to 8 we must write:
Function<Integer, String> one = new Function<Integer, String>() {
#Override
public String apply(Integer i) {
return i.toString();
}
};
now you can use it:
String resultApply = one.apply(5);
now, I think, you get the idea.

Cast One Value to Two Classes

Coming from this answer I'm wondering how I can cast an object to <T extends Number & Comparable<T>>. I mean I have a method that is supposed to sort values. And in case the values are numbers I want to compare them with each other.
My naive first attempt was
Object value1 = getAttributeValueFromHit(hit1, attributeName);
Object value2 = getAttributeValueFromHit(hit2, attributeName);
:
:
} else if (value1 instanceof Number) {
Number nValue1 = (Number & Comparable<Number>) value1;
/*
Multiple markers at this line
- Type safety: Unchecked cast from Object to Number & Comparable<Number>
- Additional bounds are not allowed in cast operator at source levels below 1.8
*/
Number nValue2 = (Number & Comparable<Number>) value2;
/* same as above */
return compareNumbers(nValue1, nValue2);
/*
Multiple markers at this line
- Type safety: Unchecked cast from Object to Number & Comparable<Number>
- Type safety: Unchecked cast from Object to Number & Comparable<Number>
- Bound mismatch: The generic method compareNumbers(T, T) of type DataHitComparator is not applicable for the arguments (Number, Number). The inferred type Number is not a valid substitute for the bounded parameter <T extends Number & Comparable<T>>
- Bound mismatch: The generic method compareNumbers(T, T) of type DataHitComparator is not applicable for the arguments (Number & Comparable<Number>, Number & Comparable<Number>). The inferred type Number & Comparable<Number> is not a valid substitute for the bounded parameter <T extends Number & Comparable<T>>
*/
}
compareNumbers() is based on the linked answer:
private <T extends Number & Comparable<T>> int compareNumbers(T n1, T n2) {
return n1.compareTo(n2);
}
Do I have any chance to make this work with Java 7?
Use a generic type parameter (you can define one on your method or re-use one that is defined in the scope of the class).
public static <X extends Number & Comparable<X>> int test() {
Object o1 = getAttributeValueFromHit(hit1, attributeName);
Object o2 = getAttributeValueFromHit(hit2, attributeName);
return compareNumbers((X) o1, (X) o2);
}
This will leave you with two warnings (because a cast to Comparable<X> cannot be checked) but it will not have any compile errors (and it works as well)
EDIT:
The above is absolutely true! To weave this into compareNumbers() and avoid the warnings it looks like this:
private <T extends Number & Comparable<T>> int compareNumbers(Number number1, Number number2) {
#SuppressWarnings("unchecked")
T number1Cast = (T) number1;
#SuppressWarnings("unchecked")
T number2Cast = (T) number2;
return number1Cast.compareTo(number2Cast);
}
and its call:
return compareNumbers((Number) value1, (Number) value2);

Categories