Difference between "? extends Stream<? extends R>" and "Stream<? extends R>" - java

What's the difference between
? extends Stream<? extends R>
and
Stream<? extends R>
Is <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper) same as <R> Stream<R> flatMap(Function<? super T, Stream<? extends R>> mapper).
Could you give some examples?

Short answer: ? extends SomeType is very different than SomeType.
Longer answer:
The use of Stream<extends R> as SomeType confuses the example. To answer the question, consider a simpler comparison, for example:
? extends Integer
Integer
The first observation is that ? extends Integer as a type expression can be used only within generic declarations. On the other hand, Integer can be used in many more places.
Here are some code examples to help show the difference:
// The following do not compile:
//
// Syntax error on tokens, delete these tokens ('? extends').
//
// private Integer value;
// public ? extends Integer getValue() {
// return value;
// }
//
// Syntax error on tokens, delete these tokens ('? extends').
//
// private Integer value;
// public void setInteger(? extends Integer value) {
// this.value = value;
// }
//
// In both cases, the use of bounded quantification ('? extends') is
// not valid outside of a generic type declaration.
// Here is a very basic example of the use of generics:
//
// Generic 'Wrapped' is quantified on a single type, which
// is unrestricted:
public class Wrapped<T> {
Wrapped() { this.value = null; }
Wrapped(T value) { this.value = value; }
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
}
// The following is also valid:
//
// 'Wrapped_1' is quantified on a single type, which is restricted
// to be 'Integer' or a subtype of 'Integer'.
public class Wrapped_1<T extends Integer> {
// EMPTY
}
// This is not valid. In addition to being non-valid syntacticly,
// the declaration needs a specific type. Use of a wildcard does
// not provide a specific type.
//
// Syntax error on token "?", Identifier expected
//
// public class Wrapped_2<? extends Integer> {
// }
// The following does not compile:
//
// Cannot instantiate the type Wrapped<? extends Integer>.
// Type mismatch: cannot convert from Wrapped<? extends Integer> to Wrapped<Integer>.
//
// private Wrapped<Integer> Wrapped0 = new Wrapped<? extends Integer>();
// These show the difference in effect between the declarations
// 'Integer' and '? extends Integer'.
private Wrapped<Integer> wrapped_1 = new Wrapped<Integer>( new Integer(4) );
private Wrapped<? extends Integer> wrapped_2 = wrapped_1;
{
// This compiles:
wrapped_1.set( new Integer(5) );
// This does not compile:
//
// The method set(capture#1-of ? extends Integer)
// in the type Wrapped<capture#1-of ? extends Integer>
// is not applicable for the arguments (Integer)
//
// wrapped2.set( new Integer(6) );
}

let say R = Number
Stream<? extends R> can be Stream<Integer> Stream<Long>
But
? extends Stream<? extends R> says which implements Stream<Number> or Stream<Integer> and so on....
class XXXX implements Stream<Integer>{} ...
XXXX overrides all the Stream abstract methods

Related

Implementation a variation of `Optional.or()` method

I am currently learning about the functionalities of the Optional class, and I am trying to build a simplified version of the Optional class. I was able to code ifPresent(), filter(), of(), map() and so on. However, I am currently stuck with the implementing or().
I know that or() have the signature Optional<T> or(Supplier<? extends Optional<? extends T>> supplier). However, my implementation assumed that I can access the contents of the Optional. As show below:
class Optional<T> {
private final T item;
...
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
if (this.item == null) {
T item = supplier.get().item;
return Maybe.<T>of(item);
} else {
return this;
}
}
}
As you can see, T item = supplier.get().item would throw an error saying that .item is inaccessible due to it being private. How am I able to access the item without causing this error?
First, you need to recall that you can not access a private field through an instance of a subtype, even though assigning the subtype reference to a variable of the current type, which allows the access, is possible without cast.
So if you have
public class ClassWithPrivateField {
private String field;
static class Subclass extends ClassWithPrivateField {}
void someMethod(Subclass obj) {
String s = obj.field; // does not work, you can't access field through Subclass
}
}
you may write
public class ClassWithPrivateField {
private String field;
static class Subclass extends ClassWithPrivateField {}
void someMethod(Subclass obj) {
ClassWithPrivateField withBroaderType = obj; // always works
String s = withBroaderType.field; // now, no problem to access field
}
}
Now to your more complicated generic variant. If you have
public class Optional<T> {
private final T item;
private Optional(T t) {
item = t;
}
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
if(this.item == null) {
T item = supplier.get().item;
return Optional.of(item);
}
else return this;
}
private static <T> Optional<T> of(T item2) {
return new Optional<>(item2);
}
}
the access to item is rejected by the compiler because the type returned by the supplier is ? extends Optional<? extends T> which is a subtype of Optional<? extends T>, just the same way as Subclass is a subtype of ClassWithPrivateField.
You can fix the issue the same way, by introducing a variable:
public class Optional<T> {
private final T item;
private Optional(T t) {
item = t;
}
Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
if(this.item == null) {
Optional<? extends T> optional = supplier.get(); // valid assignment
T item = optional.item; // valid access
return Optional.of(item);
}
else return this;
}
private static <T> Optional<T> of(T item2) {
return new Optional<>(item2);
}
}
Alternatively, you could insert a type cast to Optional<? extends T> like
T item = ((Optional<? extends T>)supplier.get()).item;
but I would prefer the variant with a variable as it immediately shows to the reader that the assignment (without a cast) is a valid type transition which can never fail. The type cast can not fail either and is a no-op at runtime, but its syntax is indistinguishable from type casts performing a runtime check that could fail.
You just need to replace
T item = supplier.get().item;
return Maybe.<T>of(item);
with
return (Optional<T>)supplier.get();

The type of getMethod() from the type MyClass is String, this is incompatible with the descriptor's return type: U

I have a simple java class with some variables String, Double, Integer etc.
public class MyClass {
private String name;
private String status;
private Double risk;
private Double health;
// more variables with all getters and setters
}
I am trying to write a generic method which will return the Function<T, U> type. I will further use this function for sorting. It is throwing compile time error
The type of getName() from the type MyClass is String, this is incompatible with the descriptor's return type: U
at line func = MyClass::getName;
and error
The type of getRisk() from the type MyClass is Double, this is incompatible with the descriptor's return type: U
at line func = MyClass::getRisk;
private static <T extends MyClass, U extends Comparable<U>> Function<T, U> getSortFunction(final String fieldName) {
Function<T, U> func = null;
if ("name".equalsIgnoreCase(fieldName)) {
func = MyClass::getName;
} else if ("risk".equalsIgnoreCase(fieldName)) {
func = MyClass::getRisk;
}
return func;
}
The return type of my function is of Comparable type not sure what wrong I am doing here. Any pointers?
<T extends MyClass, U extends Comparable<U>> : This is type inference problem. This has be discussed in a question: Very confused by Java 8 Comparator type inference
To fix the problem you can do the following:
Change the return type: private static <T extends MyClass, U extends Comparable<U>> Function<T, U> to private static Comparator<MyClass>?
Return Comparator.comparing based on the field name:
if ("name".equalsIgnoreCase(fieldName)) {
func = Comparator.comparing(MyClass::getName);
Complete code:
private static Comparator<MyClass> getSortFunction(final String fieldName) {
Comparator<MyClass> func = null;
if ("name".equalsIgnoreCase(fieldName)) {
func = Comparator.comparing(MyClass::getName);
} else if ("risk".equalsIgnoreCase(fieldName)) {
func = Comparator.comparing(MyClass::getRisk);
}
return func;
}
public static void main(String[] args) {
List<MyClass> myClassList = //init list;
myClassList.sort(getSortFunction("name"));
}
Java Generics is all about you as developer promising that the instances used/returned will fulfill some type restrictions.
So, what is it that you promise about the result type of getSortFunction()? You write:
private static <T extends MyClass, U extends Comparable<U>> Function<T, U> getSortFunction(final String fieldName)
meaning:
The method will return a Function accepting T and returning U.
The Function will accept some unspecified subclass T of MyClass.
The Function will return instances of U, being some Comparable class.
When the compiler sees a call of e.g. getSortFunction("name"), he has no hint what to conclude for T and U, whether the resulting Function will be a Function<MyClass,String> or a Function<MySubclass,Long>, so the generics part of your declaration isn't helpful. The compiler's only chance is to look at the expected result of the method call, e.g.
Function<MyClass,String> fun = getSortFunction("hometown");
In this case, T is MyClass, and U is String. Of course, the method body must be written in a way applicable to all possible call patterns, so the same method body must match both a call expecting a Function<MyClass,String> and one expecting a Function<MySubclass,Long>. Returning MyClass::getName only matches the first call pattern and not e.g. a Function<MySubclass,Long>.
That's why you get the compile error.

Use of Java 8 Lambdas with Generics

Is it possible to do this using Predicate interface.
I have a client class that utilizes functions provided by a MathUtility class. Whatever the Mathmatical operation it should happen only within the MathUtility class.
//in client
MathUtility.sum(listOfInts, (Integer i)->{return (i<3);});
//in utility
class MathUtility<T extends Number> {
public static <T extends Number> T sumWithCondition(List<T> numbers, Predicate<T> condition) {
return numbers.parallelStream()
.filter(condition)
.map(i -> i)
.reduce(0, T::sum); //compile time error
}
public static <T extends Number> T avgWithCondition(List<T> numbers, Predicate<T> condition) {
//another function
}
//lot many functions go here
}
Right now it fails with this error - The method reduce(T, BinaryOperator<T>) in the type Stream<T> is not applicable for the arguments (int, T::sum)
Note: I do not want to write sum functions for different Number types
EDIT: Detailed discussion on this topic covered in this Github Notebook
Is there a way to do it without writing a sum function for every possible type of T that i'm expecting?
As Aaron Davis stated in a comment above, you can pass the reduction parameters to the method itself.
public static <T> T sumWithCondition(List<T> numbers, Predicate<T> condition, T identity, BinaryOperator<T> accumulator) {
return numbers.parallelStream().filter(condition).reduce(identity, accumulator);
}
An example would be:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(sumWithCondition(list, i -> i > 1, 0, (a, b) -> a + b));
>> 14
List<BigInteger> list2 = Arrays.asList(BigInteger.ONE, BigInteger.ONE);
System.out.println(sumWithCondition(list2, i -> true, BigInteger.ZERO, (a, b) -> a.add(b)));
>> 2
you must point out which actual type of Number to be summed, Since the Number class has no static sum method.
you must assign identity with type of T extends Number,0 is an concrete type of Integer and does not compatible with type of T.
Possible Solution
you can make which actual type of Number to be summed later, for example:
Integer sumToInt = MathUtility.sum(numbers, condition).as(Integer.class);
Double sumToDouble = MathUtility.sum(numbers, condition).as(Double.class);
OR you can make which actual type of Number to be summed ahead, when using this style you are free to take type of actual Number to every sum to be called, one the other hand, you can reuse it without taking any confused parameters and which is exactly what you want,for example:
SumOp<Integer> sumIntOp = SumOp.of(Integer.class);
//sumIntOp is reused twice.
Integer sumToInt1 = sumIntOp.sum(numbers1, condition1);
Integer sumToInt2 = sumIntOp.sum(numbers2, condition2);
MathUtility
class MathUtility {
private static <T extends Number> Sum sum(List<T> numbers,
Predicate<T> condition) {
return sum(numbers.parallelStream().filter(condition));
}
private static <T extends Number> Sum sum(Stream<T> stream) {
return new Sum() {
public <T extends Number> T as(Class<T> type) {
return SumOp.of(type).sum(stream);
}
};
}
interface Sum {
<T extends Number> T as(Class<T> type);
}
}
SumOp
public class SumOp<T extends Number> {
private static final Map<Class<?>, SumOp<?>> OPERATORS = new HashMap<>();
private final T identity;
private final BinaryOperator<T> plusOp;
private final Function<Number, T> valueExtractor;
static {
register(Integer.class, new SumOp<>(0, Integer::sum, Number::intValue));
register(Double.class, new SumOp<>(0., Double::sum, Number::doubleValue));
//todo: add more SumOp for other Number types
}
public static <T extends Number> void register(Class<T> type,
SumOp<T> sumOp) {
OPERATORS.put(type, sumOp);
}
public static <T extends Number> SumOp<T> of(Class<T> type) {
return (SumOp<T>) OPERATORS.computeIfAbsent(type, it -> {
String message = "No SumOp registered for type:" + type.getName();
throw new IllegalArgumentException(message);
});
}
public SumOp(T identity,
BinaryOperator<T> plusOp,
Function<Number, T> valueExtractor) {
this.identity = identity;
this.valueExtractor = valueExtractor;
this.plusOp = plusOp;
}
public <I extends Number> T sum(List<I> numbers,
Predicate<I> condition) {
return sum(numbers.stream().filter(condition));
}
public T sum(Stream<? extends Number> stream) {
return stream.reduce(identity, this::plus, plusOp);
}
private T plus(Number augend, Number addend) {
return plusOp.apply(valueIn(augend), valueIn(addend));
}
private T valueIn(Number it) {
return valueExtractor.apply(it);
}
}
A much simpler approach I tired is this.
The point to be noted is that the addition logic doesn't happen at the invoking side instead only within the MathUtility.
The downside here is that you have to create Addition classes for every Number type you want the + operation.
System.out.println(
MathUtility.sum(listOfInts, i->i<4, new MathUtility.IntegerAddition()).get()
);
class MathUtility<T extends Number> {
static class IntegerAddition implements BinaryOperator<Integer> {
#Override
public Integer apply(Integer t, Integer u) {
return t + u;
}
}
public static <T extends Number> Optional<T> sum(List<T> list, Predicate<T> condition, BinaryOperator<T> operation){
//ability to add is only here
return list.parallelStream()
.filter(condition)
.map(i -> i)
.reduce(operation);
}
}
The answer is yes, that should be possible. The you defined is not known to have the method "sum", therefore the compiler complains. Try to define
public interace SumInterface {
public int sum(int a, int b);
}
(I haven't tried this code in IDE but this should do the trick)

Java Generics Wildcard Capture Warning

The SCCE below shows 2 classes (B and C) implementing the interface Marker. For each class that implements Marker there is a corresponding class implementing the generic Handler interface (B_Handler, C_Handler). A map is used to associate the Class type of Pair.second to it's associated Handler. The code executes as anticipated; however, I get a compile-time warning:
warning: [unchecked] unchecked cast
Handler h1 = (Handler) (dispatch.get(p1.second.getClass()));
required: Handler
found: Handler
where CAP#1 is a fresh type-variable:
CAP#1 extends Marker from capture of ? extends Marker
What's the cleanest way to resolve this besides #SuppressWarnings(value = "unchecked")?
package genericpair;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingUtilities;
public class GenericPair
{
public class A
{
}
public interface Marker
{
}
public class B implements Marker
{
}
public class C implements Marker
{
}
public Pair<A, Marker> getTarget()
{
A a = new A();
C c = new C();
return new Pair<>(a, c);
}
public interface Handler<T extends Marker>
{
void handle(Pair<A, T> target);
}
public class B_Handler implements Handler<B>
{
#Override
public void handle(Pair<A, B> target)
{
System.out.println("B");
}
}
public class C_Handler implements Handler<C>
{
#Override
public void handle(Pair<A, C> target)
{
System.out.println("C");
}
}
public class Pair<F, S>
{
public final F first;
public final S second;
public Pair(F first, S second)
{
this.first = first;
this.second = second;
}
}
private void executeSCCE()
{
// register a handler for each Marker type
Map<Class, Handler<? extends Marker>> dispatch = new HashMap<>();
dispatch.put(B.class, new B_Handler());
dispatch.put(C.class, new C_Handler());
// get a target (e.g., Pair<A,C>)
Pair<A, Marker> p1 = getTarget();
// select handler based on the class type of the second parameter
Handler<Marker> h1 = (Handler<Marker>) (dispatch.get(p1.second.getClass()));
h1.handle(p1);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> new GenericPair().executeSCCE());
}
}
Consider the following example:
List<? extends List> test1 = new ArrayList<>();
List<List> test2 = (List<List>) test1;
Here we get the warning:
warning: [unchecked] unchecked cast
List<List> test2 = (List<List>) test1;
^
required: List<List>
found: List<CAP#1>
where CAP#1 is a fresh type-variable:
CAP#1 extends List from capture of ? extends List
This happens because there is no way to ensure that the generic constraint of List<List> will match List<? extends List>. Imagine that we rewrite this example to the following:
List<? extends List> test1 = new ArrayList<ArrayList>();
List<List> test2 = (List<List>) test1;
test1.add(new LinkedList<>());//ERROR no suitable method found for add(LinkedList<Object>)
test2.add(new LinkedList<>());//Will work fine!!
Here it is more obvious that the initial contract is broken. The list defined to contain ArrayList now contains a LinkedList. This is unsafe, and is why you are getting this warning. So there is no way to cast from Handler<? extends Marker> to Handler<Marker> safely.
There are several issues.
The first is that your Map is not able to express the type relationship between each key and its value. So if you pass a Class<T> to dispatch.get(), you only get a Handler<? extends Marker> back, not Handler<T>. In fact, there is no type you can give dispatch to make that work. Instead, you have to make a wrapper class to enforce this relationship via its API:
public class ClassToHandlerMap
{
private final Map<Class<?>, Handler<?>> map = new HashMap<>();
public <T extends Marker> void put(Class<T> clazz, Handler<T> handler) {
map.put(clazz, handler);
}
#SuppressWarnings("unchecked")
public <T extends Marker> Handler<T> get(Class<T> clazz) {
return (Handler<T>)map.get(clazz);
}
}
Note that you do still have to suppress unchecked warnings inside this class, but at least here you know it's provably correct, based on how things are allowed to be put into the map. The unchecked cast is just an implementation detail that the user of this class doesn't need to know about.
The second issue is that getTarget() should probably return Pair<A, ? extends Marker> instead of Pair<A, Marker>. You don't ever have a Handlers of Marker; rather, you have Handlers of particular types of Marker. So it makes sense that you only use Pairs of particular types of Marker too.
public Pair<A, ? extends Marker> getTarget()
{
A a = new A();
C c = new C();
return new Pair<>(a, c);
}
The last part of your function basically is using p1 to operate on itself, so we need to use a capture helper to "capture" the ? in the type of p1 into a useful type variable for what we need to do.
However, this is more complicated in this case, because you are using .getClass(). foo.getClass() has the type Class<? extends |X|> where |X| is the erasure of the compile-time type of foo. So no matter if p1 had the type Pair<A, ?> or Pair<A, T>, p1.second.getClass() would still return the type Class<? extends Marker>. So capturing on the ? in Pair<A, ?> is not enough; instead, we should capture on the ? in the return of .getClass():
#SuppressWarnings("unchecked")
private static <T extends Marker> void captureHelper(Class<T> clazz,
Pair<A, ? extends Marker> p, ClassToHandlerMap dispatch) {
Pair<A, T> p1 = (Pair<A, T>)p;
Handler<T> h1 = dispatch.get(clazz);
h1.handle(p1);
}
Unfortunately, we will have to do an unchecked cast here also. Due to the peculiar return type of .getClass() we are unable to connect the types of the return of .getClass() and the expression it is called on. And we can't use runtime casting like .cast() to cast between parameterized types (we could use .cast() to get rid of unchecked casts if we were taking an instance of the given class as an argument, but not here). There may be some edge cases in which this is incorrect, but as long as you always use Pair with the second type argument being a final implementing class, it should be correct.
And finally the primary method looks like this:
private void executeSCCE()
{
// register a handler for each Marker type
ClassToHandlerMap dispatch = new ClassToHandlerMap();
dispatch.put(B.class, new B_Handler());
dispatch.put(C.class, new C_Handler());
// get a target (e.g., Pair<A,C>)
Pair<A, ? extends Marker> p1 = getTarget();
// select handler based on the class type of the second parameter
captureHelper(p1.second.getClass(), p1, dispatch);
}

java - How to get the type of the parameter from a parameterized argument

I'm having troubles trying to find a solution, if any, to this:
public class Generics {
Map<Class<? extends SomeObject1>, SomeObject2>> map;
map = new HashMap<Class<? extends SomeObject1>, SomeObject2>>();
public static <E extends SomeObject1> SomeObject2 get(Class<E> c) {
if (map.containsKey(c))
return map.get(c);
else {
SomeObject2 o = new SomeObject2();
map.put(c, o);
return o;
}
}
}
...
//somewhere
public <T extends SomeObject1> void aMethod(AnInterestedClass<T> list) {
// How to get the value from the map
// knowing that the key is of type T?
Generics.get();
}
Ideas?
Because of type erasure, you can only do this by passing a Class object to aMethod. See this related thread.

Categories