I am trying to compile a former co-worker's code but it says that the method unmodifiableList()
can not be applied to a given type. The code in Eclipse does not show any error. But it still does not let me compile it. What could be the error?
package framework.interview.demographics;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.xmlbeans.impl.xb.xsdschema.Public;
import framework.data.people.NonReference;
import framework.data.people.people;
public class schedualData {
private final List<people> schedual;
private schedualData(List<people> schedual) {
this.schedual = Objects.requireNonNull(schedual);
}
public static schedualData getSchedualData(List<people> schedual) {
if(schedual.size() < 1)
throw new IllegalArgumentException("schedual must contain at least one people");
if(Stream.of(schedual).filter(people -> (!(people instanceof NonReference))).count() != 1)
throw new IllegalArgumentException("There must be one and only one Reference between" + "People, number, and Review");
return new schedualData(schedual);
}
//****** Getters ******\\
public people getReference() {
return schedual.stream()
.filter(people -> !(people instanceof NonReference))
.toArray(people[]::new)[0];
}
public List<NonReference> getNonReferenceschedual() {
//This is where the error is showing.
return Collections
.unmodifiableList(schedual.stream()
.filter(NonReference.class::isInstance)
.map(x -> (NonReference) x)
.collect(Collectors.toCollection (ArrayList<NonReference>::new)));
}
public List<people> getFullschedual() {
return Collections.unmodifiableList(schedual);
}
public int size() {
return schedual.size();
}
}
This is the error log/information that eclipse prints once I compile the application:
[INFO] BUILD FAILURE
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler- plugin:3.6.1:compile (default-compile) on project
AutomationTesting: Compilation failure: Compilation failure:
[ERROR] /C:/Users/Newbie/eclipse- workspace/automationTesting/Data.java:[42,35] method unmodifiableList in class java.util.
Collections cannot be applied to given types;
[ERROR] required: java.util.List<? extends T>
[ERROR] found: java.util.Collection<framework.data.people.NonReference>
[ERROR] reason: inferred type does not conform to upper bound(s)
[ERROR] inferred: java.lang.Object&java.util.List<? extends java.lang.Object>&java.util.Collection<framework.data.people.NonReference>
[ERROR] upper bound(s): java.util.Collection<framework.data.people.NonReference>,java.util.List<? extends java.lang.Object>,java.lang.
ObjectCompilation failure: Compilation failure:
[ERROR] /C:/Users/Newbie/eclipse-workspace/automationTesting/Data.java:
[42,35] method unmodifiableList in class java.util.Collections
cannot be applied to given types;
[ERROR] required: java.util.List<? extends T>
[ERROR] found: java.util.Collection<framework.data.people.NonReference>
[ERROR] reason: inferred type does not conform to upper bound(s)
[ERROR] inferred: java.lang.Object&java.util.List<? extends java.lang.Object>&java.util.Collection<framework.data.people.NonReference>
[ERROR] upper bound(s): java.util.Collection<framework.data.people.NonReference>,java.util.List<? extends java.lang.Object>,java.lang.Object
You need to explicitly declare generic type parameters. For some reason*, it can't be inferred.
return Collections.<NonReference>unmodifiableList(schedual.stream()
.filter(NonReference.class::isInstance)
.map(NonReference.class::cast)
.collect(Collectors.toCollection(ArrayList::new)));
or
return Collections.unmodifiableList(schedual.stream()
.filter(NonReference.class::isInstance)
.map(NonReference.class::cast)
.collect(Collectors.<NonReference, List<NonReference>>toCollection(ArrayList::new)));
or
ArrayList<NonReference> result = schedual.stream()
.filter(NonReference.class::isInstance)
.map(NonReference.class::cast)
.collect(Collectors.toCollection(ArrayList::new));
return Collections.unmodifiableList(result);
Though, you could simply go with
return Collections.unmodifiableList(schedual.stream()
.filter(NonReference.class::isInstance)
.map(NonReference.class::cast)
.collect(Collectors.toList()));
*The problem is that Collections.unmodifiableList
determines the type for collect(Collectors.toCollection())
, and not vice versa, as you were probably expecting.
You may help the compiler with type inference by stating exactly what you want. You say either what unmodifiableList
should take or what .collect(Collectors.toCollection())
should return.
Any of the four snippets mentioned above will help you to resolve the issue.
x -> (NonReference) x
can be replaced with NonReference.class::cast
.