So I have this situation. I've been given the task of adding the contents of one list to another list. Sounds simple enough. My problem is this, the existing list has the following syntax :
// Existing code
List<? extends ProductCatalog> listProduct = null;
listProduct = RetrieveService.getInstance().getListProduct("client1");
// My code is
List<? extends ProductCatalog> listProduct2 = null;
listProduct2 = RetrieveService.getInstance().getListProduct("client2");
If listProduct was a normal List, I'd just use AddAll. But it doesn't work with extend. Or most probably, I'm doing it wrong. So in this example, how would I add listProduct2 to listProduct.
Any help would be appreciated.
It's not possible in a type-safe way. Also see e.g. How can I add to List<? extends Number> data structures?
You might combine them both in a new List<ProductCatalog>, depending on the goal that you want to achieve.
If is mandatory the use of <? extends ProductCatalog> will be difficult, but if you can implement an empty interface in your class ProductCatalog and then declare List<your_interface> listProduct it could work.
Can you avoid the extends keyword in the generics and use <ProductCatalog> only? That could make you life easier.
However, generics are a compile time construct. So you could write a method that has the two lists as arguments without generics. This way you can put anything in the list. But it is not a clean way and may cause some other problems especially if you have a source code quality check;-)
add(clientProduct, clientProduct2);
private void add(List clientProduct, List clientProduct2){
clientProduct.addAll(clientProduct2);
}
Related
Is it possible to create a List storing elements, which are objects of class of another object?
What I mean is: is it possible to make something like that, but with successful compilation?
private SomeRow row = getRow(); // method getRow returns
// different classes, which extends SomeRow
List<row.class> rows; // how is it possible to make something like that?
The problem is that in Selenium WebDriver, which I am using, it is impossible to use wildcards, so it is forbidden to do like this List<? extends SomeRow>.
Does anybody have some ideas how to do this? Or tell me if it is impossible at all, please.
Hmm, not sure if this answer your question, how about
List <Object> rows;
then you could cast into appropriate class later using if , probably checking instanceOf the element
This is my first question here on Stackoverflow, so if I'm doing something wrong, please tell me so I can improve it the next time.
Since it's been a while since I've done some programming in Java and even then only some simple stuff, I'm still learning a lot about a lot off features and find it helpful to read discussions on this site.
I thought I understood the way Generics worked until I faced the following problem. I understand it isn't the nicest design or there are ways to solve it in another way, but let's say it must be done this way.
(It is intended as a low layer in the application, so I liked Generics to make a connection with the layer on top.)
Situation
A base class Identifieable is extended by Groupable, a class which can be extended by an Item, Mutation, Location, etc.
As groups must be made of these things, I added:
class Group<T extends Groupable> extends Groupable
{
public Group(Id id)
{
super(id);
content = new HashMap<T, Integer>();
}
private final HashMap<T, Integer> content;
// Additional methods for adding, removing etc.
}
I added the Generic here to restrict to be able to restrict a group to items, mutations, etc. A group must be groupable too.
As I want to be able to know which groups I am part of I designed my Groupable as follows:
class Groupable extends Identifieable
{
public Groupable(Id id)
{
super(id);
partOf = new ArrayList<Group<? extends Groupable>>();
}
private ArrayList<Group<? extends Groupable>> partOf;
private final ArrayList<Group<? extends Groupable>> containingGroups()
{
return partOf;
}
}
Problem
The Generic type of 'partOf' is what pains me. I need to return a list of groups of a type which extends Groupable (of course), and indirectly supers the class this object is an instance of. A Mutation cannot be part of a list of Items of course.
I've considered using a type parameter in Groupable, but this does not seem correct to me.
That way you instantiate an Item which has it's class as a type for it's parent, which is possible but not nice. This way it is possible to return and store Groups of its own type but not Groups of super-type.
Finally
I don't know if this is clear, I really don't know how to simplify the problem with preserving all elements.
If a brilliant problem-solving design exists which keeps in mind all these classes are meant to be extended and used in an as "generic" ;) manner possible, many thanks.
I've read about just using raw type, but that doesn't seem right although it is already safe to assume no bad casting would happen. If someone can explain what Java does with this Generic-nesting with wildcards and the correct way to solve this specific problem, again many thanks.
I'm more interested in a correct way, or theoretical explanation than a workaround, don't have errors yet, because I don't know how to implement it.
You cannot prescribe to the Groupable class to contain a collection of Groups. The primary reason it is so is that the Group class extends Groupable, and therefore it is not (cannot be) known at the time when the Groupable class is compiled.
There other issue here is that it does not really make sense (to me). For instance, what if the Groupable class was extended by the Item class. Would it make sense for it to contain a collection of Groups - taking into account that it would basically be its sibling but the only thing that would connect them is a common parent.
I would suggest to modify the code this way:
class Groupable extends Identifiable
{
private ArrayList<? extends Groupable> partOf;
public Groupable(String id)
{
partOf = new ArrayList<Groupable>();
}
private final ArrayList<? extends Groupable> containingGroups()
{
return partOf;
}
}
I need in my program collection in collection in collection. So something like this:
ArrayList<ArrayList<ArrayList<String>>>
You can see this does not look good. Mainly when i am using a lot of generics. So i created something like this:
public class ThreeDimensionArray extends ArrayList<TwoDimensionArray> { }
class TwoDimensionArray extends ArrayList<ArrayList<String>> { }
is this solution bad in some way or is it ok?
It's not great, but it is ok. It's rather masking what you are doing - and its a bit wasteful as you are creating a concrete class to define something that type erasure would have turned into a standard List at compile time.
Really you should be using List rather than ArrayList and the diamond operator, both changes will make the original tidier:
List<List<List<String>>> 3dList = new ArrayList<>();
If you do go down the defined class route at least use generics -
class TwoDimensionArray<T> extends ArrayList<ArrayList<T>> { }
Then you can use it for multiple types.
For anyone who might have a question like this, you probably need "Collections.sort", not "Collection.sort", the mistake I made below.
I have defined a class defined as
public class Store implements Serializable, Comparable<Store> { ... }
I have a field in another class defined as:
ArrayList<Store> fStores = new ArrayList<Store>();
I want to sort this collection, so in a method I call:
Collection.sort(fStores);
However, I get the following compilation error:
The method sort(ArrayList<Store>) is undefined for the type Collection
ArrayList implements List, and from the documentation:
public static <T extends Comparable<? super T>> void sort(List<T> list)
So, why do I get the error? I have also tried creating my own descendant of Comparator and passing that to the sort method with no luck.
I'm guessing there's something about "< T extends Comparable< ? super T > >" I'm not understanding... ?
There are basically 2 things that you need to look at :
Collections
From the Collections
This class consists exclusively of static methods that operate on or return collections. It contains polymorphic algorithms that operate on collections, "wrappers", which return a new collection backed by a specified collection, and a few other odds and ends
So basically if you have to sort or do any such kind of algorithms use this.
Next is :->
Collection
This is an interface that provides the basis of Java's collection framework. It does not include Map and Sorted Map. It represents a group of objects known as its elements and has implementations for concrete implementations. You need to think of this when you want to work with ArrayLists and Maps.
So, bottom line, you have a static algorithm to run which is present in Collections. So, use Collections.sort
You need to write Collections instead of Collection. They're related, but different. :-)
It's Collection**s**, not Collection:
http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html
vs.
http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html
Did you mean Collections.sort() (collections plural)?
It's Collections.sort() with an s.
import java.util.Collections and you should be fine.
Your issue is that you are calling Collection.sort(), not Collections.sort()
These are two separate classes:
Collections
Collection
Collection is an interface while Collections is a utility class.
Also, if you are using eclipse, double check that the import statement for Collections is the right one!
In case you got here due to a similar error:
The method sort(Comparator<...>) is undefined for the type List<...>
Then you're probably using JDK lower then 1.8. Change it in Java Build Path:
I have read that the following code snippet will result in a compiler error
void tryAddingToList(List<? extends SuperType> list) {
list.add(new SubType());
}
Now my question is:
Who exactly sets the restriction and how is the restriction set? Does the compiler specifically check for the add method call in such a method implementation?
If yes, what if I implement my own List and instead of add, introduce a new addToList method that does the same thing as add, and call that in the tryAddingToList method?
Even better, what if I implement my get method such that it also "secretly" adds something to the list (don't ask me why anyone would do that; I'm just curious).
You should use super instead of extends here.
void tryAddingToList(List<? super SubType> list) {
list.add(new SubType());
}
Assume there are 3 types SuperType, SubType1, SubType2. In your original code, List<? extends SuperType> could be List<SubType2>, and you can't add a SubType1 to List<SubType2>.
You should cast SubType to SuperType explicitly. Because not all objects of SuperType are SubType(may be typed other sub-classes). This may give you some hint. Good luck.
Yes, it's indeed the compiler that applies the restriction. Most of the information (not all) will be erased when actually compiled to byte code. You should interpreted generics as extra information for the developer, so we don't make silly mistakes.