Cannot convert from Collection<> to List<> [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am trying to validate a result from a library (Panache / Hibernate using Quarkus) by passing the object to a "validator", where the validator validates that the result is not empty and subsequently returns the passed object back to the caller.
In this example, listAll() is from PanacheEntityBase and simply returns a list of Employee objects. If this List is empty, as in, there are no results in the result set, it does not throw an exception. So to avoid having an empty / null check in every call, I am writing the follow convenience class to validate all results.
In my validator:
public class ResultValidator {
public static <T> Collection<T> validate(Collection<T> result, Class<T> type) throws EmptyResultException {
if (result.isEmpty()) {
throw new EmptyResultException();
}
return result;
}
}
The caller would invoke this like:
return ResultValidator.validate(listAll(), Employee.class);
Rather, I'm having to upcast:
return (List<Employee>) ResultValidator.validate(listAll(), Employee.class);
The code above, that invokes validate, results in a compiler error Cannot convert from Collection<> to List<>. Unless I'm upcasting to List<> or explicitly defining List<> type in my validate implementation, I will get this error.
What do I need to change in my validate(Collection, Class) implementation to avoid upcasting or declaring an explicit type?

If your intent is to return 'self', then:
public static <T, C extends Collection<T>> C validate(C result, Class<T> type) {
// note that requiring a `Class<T>` is a code smell...
if (result.isEmpty()) throw new EmptyResultException();
return result;
}
List<String> list = ...;
list = validate(list, String.class);
now works fine, but note that it is not possible to make a new C instance. You're either returning result straight up, and therefore the fact that validate returns at all is, at best, some code/API convenience but not inherently useful, or, you can't use this, and you'd need a 'make a new collection' factory. That would get you to:
public static <T, C extends Collection<T>> C validate(C result, Class<T> type, Supplier<C> collectionMaker) {
...
}
Where the caller would have to provide something. e.g.:
List<String> list = ...;
validate(list, String.class, () -> new ArrayList<String>());

Related

Understanding Java 8 Lambda Expressions [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I was reading this article on Java 8 and had the following questions/comments I would appreciate some feedback/response.
1) Is the #FunctionalInterface declaration necessary for the following code? Or could this same code be executed without it and it is for documentation purposes? It is unclear from whether it is necessary from the article.
#FunctionalInterface
private interface DTOSender {
void send(String accountId, DTO dto);
}
void sendDTO(BisnessModel object, DTOSender dtoSender) {
//some logic for sending...
...
dtoSender.send(id, dto);
...
}
2) In general, can a function be passed as an argument to another function in Java 8? My understanding is only data types can be passed as arguments to functions, so I suppose it is not possible as a function is not a data type.
3) Do I need to do anything special to accomplish #2 above or can I just write my definitions of the 2 methods and just pass the one method as a parameter to the other method?
4) Can objects be passed as arguments to another function in Java 8? Do I need to do anything special to accomplish this or can I just write my definitions of the object and method and just pass the object as a parameter to the method?
#Functional Interface is just a hint, so that you don't put more methods into your interface.
It can. Many methods on Stream take functions as parameter: Stream.of(1, 2, 3).forEach(System.out::println).
Lambda is a function instance: Function<Integer, Integer> f = a -> a + 1. Edit: you can pass a function by name using method reference (see 2., println is a regular method).
I don't fully get the question. If the method consumes any argument, that is not primitive, it takes an object (everything in java except for primitives is an object).
The annotation #FunctionalInterface is not mandadory as the doc states.
In order to pass a function to your method, there has to be a matching functional interface.
interface ListFilter<T> {
boolean test(T item);
}
public static <T extends Comparable<T>> List<T> filter(List<T> list, ListFilter<T> filter) {
List<T> filteredList = new ArrayList<>();
for (T t : list) {
if (filter.test(t)) {
filteredList.add(t);
}
}
return filteredList;
}
public static boolean isNumberGreaterThan2(Integer integer){
return integer > 2;
}
public static void main(String[] args) {
List<Integer> list = List.of(1, 2, 3, 4);
filter(list, new ListFilter<Integer>() {
#Override
public boolean test(Integer item) {
return item > 2;
}
});
// or
filter(list, item -> item > 2);
// or
filter(list, Main::isNumberGreaterThan2);
}

Java Collection Type Parameter to array

I want to create a helper method which gets Collection type parameter to return a list. This is what I have now:
public class Helper {
public static <T> T[] CollectionToArray(Collection<T> collection) {
return collection.stream().toArray(Object[]::new); // Error
}
public static <T> T[] ListToArray(List<T> list) {
return list.stream().toArray(Object[]::new); // Error
}
}
public class IamSoNoob {
public void PleaseHelpMe() {
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
String[] arrayFromList = Helper.CollectionToArray(list); // Error
String[] arrayFromSet = Helper.CollectionToArray(set); // Error
String[] array = Helper.ListToArray(list); // Error
}
}
My questions are:
Is it possible to complete CollectionToArray(Collection<T>)?
If so, how?
Also, is it possible to pass List and Set as a parameter in the first place?
Is it possible to complete ListToArray(List<T> list)?
If so, how?
But here are some restrictions due to my personal taste.
I don't want to use #SuppressWarnings
I really want to keep the part .stream().toArray(Object[]::new) (Java 8 part!)
And I have a feeling that I need to fix the part Object[]::new by using something like: <T extends Object> or <? extends T> but I can't really figure out.
Please help me out, and please provide an explanation as well, I am often confused by Generic and ?.
No, you absolutely cannot do it, if it were possible the library method Collection.toArray() would've given you the same type as your LHS but instead when you want the exact type as your LHS you have to use Collection.toArray(T[]) (even that comes with ArrayStoreExceptions i.e it is up to the programmer to provide the right type for the array), the reason being that in your toArray() you've specified Object[] to be your array and later you cannot cast it to any other type or else it will result in a ClassCastException.
The reason for all this hullabaloo is because of the way generics works i.e its a compile time thing and at runtime Java erases all type parameters to their upper bound types and hence losing type information which is required for creating arrays.
One safe way of doing it is by adding another paramter to you helper method as
public static <T> T[] CollectionToArray(Collection<T> collection, T[] arr) {
return collection.stream().toArray(value ->Arrays.copyOf(arr,collection.size()));
}
and using it as
String[] arrayFromList = Helper.CollectionToArray(list, new String[0]);
but then everybody's better off using
Collection#toArray(T[]).

return List<T> for Generic type T [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 4 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I happened to use <T> instead of List<T> in the following code, and it works.
EDIT(sorry for not compiling code):
private <T, DAO> T getList(Class<Dao> clazz, Function<Dao, T> op) {
Jdbi jdbi = Jdbi.create("jdbc:h2:mem:test");
Handle handle = jdbi.open();
DAO dao = handle.attach(clazz);
T result = op.apply(myDao);
return result;
}
List<Data> getDataList() {
return getList(MyDao.class, MyDao::getDataList); //myDao.getDataList return List<Data>
}
I don't understand why <T> didn't error out. Can anyone tell me why?
I think this is a confusing choice for generics.
I suggest that you do this instead:
private Dao dao;
private List<Data> getList() {
return this.dao.getDataList();
}
I guess you must be having a cast to (T) as shown below in your actual code.
private <T> T getList(Dao myDao)
{
T result = (T) myDao.getDataList(); // myDao.getDataList return List<Data>
return result;
}
If yes, the the code will compile fine. You are defining getList method as returning an object of type T. Java will allow you to cast something to 'T' although with a warning.
Since there is no constraint on T in method definition. It is equivalent to 'Object' i.e your method is similar to 'private Object getList(Dao myDao){...}'
In which case the return value can be list or map or any subclass of Object.
Basically, you have not specified what 'T' stands for. If you said '<T extends List>' for example then return type must be a subclass of list.
Another way you could re-write the method, with some clarity about T:
private <T extends Object> T getList(Dao myDao)
{
T result = (T) myDao.getDataList();
// Warning Type safety: Unchecked cast from List<Data> to T
return result;
}

How to name class name according to Java Generics type return?

< T > T foo(P p) {
...
}
I'll get different types of return from foo according to the parameter I inserted, which means T changes according to p.
Then I try to call this function and use its return result.
Class x = foo(p);
What should I write in substitute of Class here?
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
Let me give the exact sample here.
public <T> List<T> getProperty(Property property) {
switch(property) {
case NAME: List<Name> names = new ArrayList<Name>();
names.add(this.name); return (List<T>) names;
case PHONE: return (List<T>) this.phones;
case EMAIL: return (List<T>) this.emails;
case ADDRESS: return (List<T>) this.addresses;
case NOTE: List<Note> notes = new ArrayList<Note>();
notes.add(this.note); return (List<T>) this.note;
default: return null;
}
}
public enum Property {
NAME, PHONE, EMAIL, ADDRESS, NOTE
}
public List<Entry> search(Property property, String s) {
if(this.isEmpty()) {
return null;
}
List<Entry> result = new ArrayList<Entry>();
for(Entry e : entries) {
if(e.getProperty(property) != null) {
for( **Object** p : e.getProperty(property)) { //What should I write instead of Object
if(p != null) {
if(p.containString(s)) { //there'll be errors if use Object. Need to know p's class.
result.add(e);
}
}
}
}
}
return this.nonDuplicatedResult(result);
}
I'm really not sure what you're asking. You haven't explained your use cases at all and haven't given us much code to look at. It's difficult to provide useful feedback from within the fog of obfuscation.
Generally speaking, if you want a method that returns a different object depending on the value of a supplied argument, then what you're probably talking about is a static factory method which can return any object that is a subtype of the method's return type. It is convenient to make such objects a part of an interface-based type system (eg. the static factories for the EnumSet class).
The use of an interface-based type system is actually necessary if you wish to return an enum, because enums cannot be part of a class hierarchy, but they can implement an interface that forms an interface-based type system.
Suppose parameter is a enum type.
enum P {
XX,YY,ZZ
}
then the return type T is Xx, Yy, Zz respectively according to parameter.
No it isn't. The return type is P. You're over-thinking this. The 'enum' case isn't a job for Generics at all.
Assuming you have an finite number of return types, you could just check through each one using instanceof to see if the returned value is of a certain type. So in this case Object would substitute class, then you could later cast it.
What is happening is basically with that method definition, what you are saying to the compiler is that your method will return whatever the parameter assignment declares itself to be. You can do that, but how your method is implemented will boil down to a compiler warning, as you can't actually ensure that you are generating the appropriate type - since you don't know it, it is never passed to the method, and erased at compile time.
More typically what you would do is:
<T extends P> T foo(T p) {
...
}
Now you get an object of the right type as a parameter, so you have some idea of what to return. That concept has little utility with enums, though.
Here is a real world example of where you could use the method definition you posed in your question:
public static <T> T generateProxy(Object realObject, Class<?>... interfaces) {
return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject));
}
Of course such a method generates a compiler warning. Now, what you are saying here is that the caller will define a variable, and will be sure to pass in at least one interface of the type they define. If they don't, they will end up with a ClassCastException at runtime, but you avoid calling code that knows what it is doing from explicitly casting.
It is debatable if that is a good idea.
So the short answer is that you can define the Class to be whatever you want - the compiler will accept anything - but if the method doesn't return the correct type, you will get an exception at runtime, so it is all about how you implement the method. Rarely can a method be smart enough to return the right thing without the correct type as a parameter. And if you can't pass in an appropriate parameter declared with the generic type to the method, you will have to deal with a compiler warning in order to return anything (other than null).

Java 6 Collections.checkedList appropriate usage

I am creating several functions in which I want to return the interface instead of the implementation, I.E. List instead of ArrayList . My method signature and a brief implementation follows:
public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>)
{
List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>();
for(MyAwesomeObject awesomeObject : awesomeObjects)
{
MyAwesomeComposedObject composedObject = new MyAwesomeComposedObject(awesomeObject);
composedObjects.add(composedObject);
}
List<MyAwesomeComposedObject> composedObjectList = Collections.checkedList<composedObjects, MyAwesomeComposedObject.class);
return composedObjectList;
}
My question is, is this an antipattern of some sort? I want to guarantee that the invoker of this method is getting the interface instead of an implementation. I also do not believe this to be a case of overengineering. If this is not the correct way to return an interface, in this scenario I am open to the correct implementation.
Attached is a small program that results in an exception:
public static void main(String[] args)
{
Vector v = (Vector) c();
}
static List<Object> c()
{
List<Object> l = new ArrayList<Object>();
l.add(new Object());
List<Object> o = Collections.checkedList(l, Object.class);
return o;
}
The javadoc is here: checked list
The List returned is a Collections.CheckedList not a Vector. You cannot the reference to a type the object is not.
However what you can do is
public static void main(String[] args) {
Vector<Object> v = new Vector<Object>(c());
}
composedObjects is already a List, you can return that.
public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>) {
List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>();
for(MyAwesomeObject awesomeObject : awesomeObjects)
composedObjects.add(new MyAwesomeComposedObject(awesomeObject));
return composedObjects;
}
For your revised question: There is no way to prevent the caller from attempting to cast to whatever they want. If it is an inappropriate cast they will get the exception. This is the very reason why casting from an interface to a concrete class is strongly discouraged.
If you are really worried about this, consider returning an ArrayList instead of a List. That should discourage casting since they are getting a concrete type. Please note that I do not endorse this, it is just an option.
I want to guarantee that the invoker of this method is getting the interface instead of an implementation
This is not valid. You are returning a List where the declared type of the elements is an interface, however each element must be SOME instantiation. All a checked collection does is prevent the addition of elements of the incorrect type. There is nothing that prevents the user from casting back to the implementation type.
If you are attempting to ensure that the user gets List instead of ArrayList (my assumption here because I don't see an interface for you Awesome class), this again is flawed because the user could still cast the List to an ArrayList although this would be a bad idea since it risks a ClassCastException.
No, I recommend to keep the code as simple as possible. Read the Javadoc for a discussion when to use Collections.checkedList
http://download.oracle.com/javase/7/docs/api/java/util/Collections.html#checkedCollection%28java.util.Collection,%20java.lang.Class%29

Categories

Resources