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.
Related
Why does this code not compile?
public class Wrapper<T> extends T {}
Is it because this is semantically never a proper design choice? Or can this physically not compile in any language because of some sort of type ambiguity?
I'd imagine you could use it to create a public class Persistent<T> extends T {} that allows you to for example extend the T with some functionality to serialize the T to a byte array and store it on disk, while still allowing instances of Persistent<T> to be passed to functions that would otherwise only take values of type T.
As such this would be possible:
EDIT: this would not be possible, as there could be no sensible implementation for load() (as correctly pointed out by michid). To not corrupt his comment though, I'll leave it here.
Integer i1 = Integer.valueOf(5);
Persistent<Integer> i2= new Persistent<Integer>();
i2.load(i1) //example method to load i1 into i2, basically serializing it
List<Integer> myIntegers = new ArrayList<>();
famousPeople.add(i1);
famousPeople.add(i2);
When you extend a class you extend the existing functionality by some additional one provided by the super class. When the super class is T it can be anything but you cannot know what. So how would you extend something you know nothing about?
I'm trying to learn how to use generics and for that, I'm creating my own data structure similar to a list with an Iterator and all.
The uppermost class is declared as:
public class BasicList<A> implements Iterable {
}
It's just a list with nodes and a single pointer to the next element.
There's another list, called DescendingList, that does pretty much the same, only this time around, you're getting another output since the Iterator is different. I'm giving a comparator to this List to get the Iterator to work. The comparator is just an interface:
public interface Bigger<A> {
boolean bigger(A x);
}
DescendingList looks like this:
public class DescendingList<A extends Bigger<A>> extends BasicList<A> implements Iterable {
}
The idea is that it could work with any kind of object that is comparable through the Bigger interface.
Now I have an abstract class:
public abstract class Rock implements Bigger<Rock> {
}
And finally, a normal class which extends the Rock class:
public class Mineral extends Rock {
}
So, the issue at hand is that, while I can easily create a new BasicList filled with Minerals like this:
BasicList<Mineral> min = new BasicList<Mineral>();
I can't do the same with the DescendingList. Whenever I try going with
DescendingList<Mineral> min = new DescendingList<Mineral>();
my IDE (IntelliJ) goes all
"Type parameter "Rock" is not within it's bound; should implement Bigger<Mineral>"
And I don't really get why that happens. I am pretty sure that I've messed up the type parameters somehow and I'm really not sure where. This should be solveable somehow (at least without removing any classes/interfaces - the class headers might be and probably are completely messed up). Thanks in advance for any help you might offer.
A Mineral isn't a Bigger<Mineral>, it's a Bigger<Rock>, and that is incompatible with Bigger<Mineral>, because even though a Mineral is a Rock, Java's generics are invariant. It needs to be a Bigger<Rock> because of how Rock is defined -- implementing Bigger<Rock> -- and that DescendingList declares type parameter A to be a Bigger<A>.
Because it's a consumer (type parameter as a method parameter), the type parameter A needs a lower-bound (super) on its declaration.
class DescendingList<A extends Bigger<? super A>> // ...
This way Mineral will be within its own bound.
As an aside, you are implementing the raw form of Iterable in BasicList; you should supply a type argument there.
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);
}
I'm trying to design a special type of collection that may only contain elements of its own type. This collection class must also be extendable. At first glance, this seems like a simple enough task:
public class MyClass<E extends MyClass> implements Collection<E>{
//insert Collection<E> methods here...
}
However, because one of these collections may only contain elements that are instances of its class, the following shouldn't be possible:
public class MySubclass extends MyClass<MyClass>{}
What I need is a version of MyClass that essentially does the following (don't try to compile this one):
public class MyClass<E extends this.getClass()> implements Collection<E>{...}
Is it possible to implement something like this? If so, how can it be done?
I think the signature your are looking for would be something like this:
public class MyClass<E extends MyClass<E>> ...
The problem with this, and why I don't think you can enforce what you want from a declaration standpoint is that you have an infinite loop. If the collection may only contain elements of its own type, then elements can only contain elements of itself, etc, etc.
You now have an infinite loop where you may only contain Collections and at no point will you have a Collection that contains some THING.
Also, remember that at runtime type-erasure does away with all generic type. Therefore, no matter how fancy your generic declaration is at any point someone could do the following and just get a warning:
new MyClass();
That is another reason why trying to enforce this type of structure probably won't work well.
Instead you could put an appropriate check in the add method that would provide runtime enforcement. Still have the infinite loop issue though.
EDIT
To do runtime checking, do the following:
public boolean add(E element){
if (!(element instanceof MyClass))
throw new IllegalArgumentException("Element is not an instance of MyClass");
// rest of add code here
}
Just hoping I could get someone to tell me I am doing this right or not, as I have never written something like this before. So I have to write a class named ProcessQueue that is a subclass of Vector, as well as a constructor that will define an empty queue. Also the Vector will be holding items of type "Object." So here it is...
public class ProcessQueue<Vector>{
ProcessQueue(){}
}
Not, that's not right. That's generic, not extending.
Besides, it's not a good idea. Your ProcessQueue might have a collection of some sort underneath, but it need not extend. Prefer composition to inheritance.
If you must implement something, start by having an API that actually looks like a Queue. There's a certain behavior that's expected; make sure that yours conforms to it. The best way is to implement an interface that enforces it.
public class ProcessQueue<T> implements Queue<T> {
// Have a private collection of some sort that provides the behavior that the interface requires
}
You're not extending Vector anywhere. Change your code to:
public class ProcessQueue<T> extends Vector<T> {
}
By the way, I don't recommend you using Vector at all. Check Why is Java Vector class considered obsolete or deprecated?. IMO if you have to do this it would be better extending ArrayList.
public class ProcessQueue<T> extends ArrayList<T> {
}
And in your code use a List:
List<SomeClass> lstQueue = new ProcessQueue<SomeClass>();
U̶n̶r̶e̶l̶a̶t̶e̶d̶ ̶t̶o̶ ̶t̶h̶e̶ ̶o̶r̶i̶g̶i̶n̶a̶l̶ ̶q̶u̶e̶s̶t̶i̶o̶n̶ , I think similar as duffymo, you should not extend any of the Java Collection classes until it is a must-do. Note that there are plenty of classes to hold almost any kind of common collections, and you have Queue and PriorityQueue that can help you in your real work.
The best solution would be as pointed by duffymo, composition instead of extending a Java Collection:
public class ProcessQueue<T> {
private List<T> data = new ArrayList<T>();
//rest of code...
}
Or creating a new implementation of an interface, like Queue or List.
public class ProcessQueue<T> implements Queue<T> {
//Queue interface methods implementation...
}