Java Idiomatic way to create generic array - java

EDIT: This is NOT a duplicate of the above question. The original question concerns a list whose type is unknown at compile time. This question concerns an array like construct of a generic list.
For example the above solution of final E[] a = (E[]) Array.newInstance(c, s); won't work because I can not obtain List<MyClass>.class And also you can't cast from Object[] to List<MyClass>[]
What is the idiomatic way to deal with an array like construct of generic type? For example, I want an array of List<MyClass>. ArrayList<List<MyClass>> myClassArray won't work directly because I need to be able to do things like myClassArray.set(5, myClassObj) even when the myClassArray.size() is 0. Initialize it with
for(int i = 0; i < mySize; i ++){
myClassArray.add(null)
}
works but it's ugly.
List<MyClass> myClassArray[] won't work either because you can't create a generic array. So what is the most idiomatic way to achieve my goal? The size of array won't change once created.

Create your own class to simulate an array.
class Array<T> {
final Object[] data;
public Array(int size) {
data = new Object[size];
}
public void set(int index, T datum) {
data[index] = datum;
}
#SuppressWarnings("unchecked")
public T get(int index) {
return (T) data[index];
}
}
Since you control the access to the underlying array, you know that the elements in there will all be of type T.

The usual way is
List<MyClass>[] myClassArray = new List[size];
The reason why the type of array of parameterized types is "unsafe" is very obscure (because arrays are supposed to check at runtime when you put something into it that it's an instance of the component type, but it's not possible to actually check the parameter for a parameterized type) and not relevant for your purposes.

Related

Java Auto Cast an Object

I'm wondering if there is a way to Auto Cast an Object to some type by storing the Class type along with the object? I thought this was possible with Java, but maybe not.
For example:
class StorageItem
{
private int itemcount;
StorageItem(int itemcount)
{
this.itemcount = itemcount;
}
int getItemCount()
{
return itemcount;
}
}
class Storage
{
private Class clazz;
private Object value;
public Storage(Class clazz, Object value)
{
this.clazz = clazz;
this.value = value;
}
//Is there a way such a call can be created to automatically cast
//the object to the class type and return that cast type in a
//generic way. The idea being that Storage knows what it should
//already be cast to. Is this possible?
public T getValue()
{
return clazz.cast(value);
}
}
A usage example:
public static void main(String[] args)
{
//Create storage item
Storage storage = new Storage(StorageItem.class, new StorageItem(1234));
//The call to getValue() will automatically cast to the Class passed
//into Storage.
int itemcount = storage.getValue().getItemCount(); //returns 1234
}
Obviously the getValue() call in Storage is a pseudocode call, but it's just there to provide the idea as to what I would like to do.
Is there anyway to have a getValue() call that will Auto cast to the Class typed stored in the Storage class. Again, the idea is that the Storage class knows what it should be cast to. Or is there anyway this can be done at all?
StorageItem is just one simple example. Here, it just stores an int for discussion purposes. However, it could be more complex.
Another usage example, would be storing the Storage object in a list.
List<Storage> row = new ArrayList<Storage>();
row.add(new Storage(StorageItem.class, 1234));
row.add(new Storage(String.class, "Jason"));
row.add(new Storage(Integer.class, 30));
row.add(new Storage(Double.class, 12.7));
Then, these can be accessed in the following way.
//calls StorageItem's getItemCount() method
row.get(0).getValue().getItemCount(); //returns 1234
//calls String's length() method
row.get(1).getValue().length(); //returns 5
//calls Integer's intValue() method
row.get(2).getValue().intValue();
//calls Integer's doubleValue() method
row.get(3).getValue().doubleValue();
If getValue() only ever returned an Object, I would have to always cast to the specific Object manually. Instead, if I can store the cast class inside the Storage object, then Storage has enough information to know what to automatically cast the Object to on the getValue() call.
If this is doable in Java is the answer to the question I'm seeking. And if so, how?
Would this do the trick? Much less hacking is required:
class Storage<T> {
private T value;
public Storage(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
I don't really see the problem that you're trying to solve here. #bali182's answer does give you a "generic" way to store a reference - but storing the reference itself is just easier.
Consider what happens if you put two Storage instances, containing differently-typed references, into a collection:
List<Storage<SOMETHING>> storages = new ArrayList<>();
storages.add(new Storage<String>("Hello"));
storages.add(new Storage<Integer>(1));
So: what is SOMETHING? Well, it has to be ?, since that is the only type which satisfies both elements.
Now, when you iterate through the list to retrieve them, you have to deal with them as Object:
for (Storage<?> storage : storages) {
Object object = storage.getValue();
// ...
}
because you don't, in general, know what the type of the stored reference is for any given element. The concrete type of object will be the concrete type of the element - String and Integer, for the list above - but you can't make use of these different types without using some means to detect that type (e.g. if (object instanceof String)).
It would just have been easier if the references were stored directly in the list:
List<Object> objects = new ArrayList<>();
storages.add("Hello");
storages.add(1;
for (Object object : objects) {
// ...
}
You still would have to do something to detect the concrete type of object; you're just doing it without the extra layer of indirection.
Although the above example is for unrelated types, it's still easier to do it with the direct references if they are the same type:
List<String> objects = Arrays.asList("Hello", "World");
for (String object : objects) {
// ...
}
Now you don't need to do anything to know the concrete type (you might, if the elements were of a non-final class, and you wanted to handle some subclasses specially), but you've still avoided needing to dereference Storage.getValue() to get at a value that you could have directly instead.

Most convenient way to initialize an array of objects

Is there a more convenient way to initialize an array of objects than doing this?
SomeClass[] someArray = new SomeClass[100];
//...
for (int i = 0; i < someArray.length; i++) {
someArray[i] = new SomeClass();
}
// ...
Use Arrays.fill()
String[] stringArray = new String[100];
Arrays.fill(stringArray, "");
It's not any faster since it iterates over the array just like you did, but it is more convenient.
Arrays.fill() code
public static void fill(Object[] a, int fromIndex, int toIndex, Object val) {
rangeCheck(a.length, fromIndex, toIndex);
for (int i=fromIndex; i<toIndex; i++)
a[i] = val;
}
Because of the immutability of String in Java, your question is a bit strange. The primary thrust suggests you are looking for this:
String[] arr = new String[100];
Arrays.fill(arr, new String());//Array utility
However, this does not actually net you anything, because you will have to effectively create a new String object whenever you replace one of those array items with a different String. This means that the act of creating a new String() is redundant and therefore less efficient.
This begs the question: why are you doing this? Is it to ensure that there is a valid object being returned? Or that the object in the array is actually a String? If the latter, make use of generics:
List<String> arr = new ArrayList<String>();
This solves the same problem and nets you benefits of object-orientation. It is generally recommended you stay away from primitive arrays if you can: object-based arrays are far more usable, leading to cleaner code and often more efficient programs.
If you are using a mutable type, and the point of pre-filling is to ensure that an object exists when it's retrieved from the array, the best way to handle this is to actually use exceptions on the receiving end, for two reasons: the first being that you save memory by not allocating memory before you actually need it (and all the attendant savings that go along with that) and the second being that there is little stopping an array from having an element set to null, so you have to check anyway:
try {
SomeObject myObj = arr.get(idx);
myObj.doSomethingFun();//will fail if this is null!
} catch (NullPointerException e) {
//do something intelligent like return a fail case.
}
Note that while exceptions carry overhead if they catch an actual error, they have no overhead until that point. For this reason you don't want to use them for flow-of-control, but you do want to use them (more than you probably do) to catch edge cases that don't make sense.
This isn't quicker, but its less code:
String[] stringArray = new String[100];
Arrays.fill(stringArray, "");
So, you told you want to create array of distinct objects. Then there must be a default constructor or a factory that you pass in. I'll show code for first case - when you can call empty constructor with Class<...>.newInstance():
import java.lang.reflect.Array;
// ... in a class:
#SuppressWarnings("unchecked")
public static <T> T[] initializedArray(int size, Class<T> classHint) throws java.lang.Exception {
T[] result = (T[]) Array.newInstance(classHint, size);
for (int i = 0; i < size; ++i) {
result[i] = classHint.newInstance();
}
return result;
}
Example usage here: http://ideone.com/pbTFq9
you can declare like
String[] array;
...
array = new String[]{object1, object2};

Java create array from generic runtime type of another array

I have the following code which merges two arrays and should handle any type apart from primitives.
#SuppressWarnings("unchecked")
public static synchronized <E> E[] aryMergeNoDup(E[]... arys){
HashSet<E> hs = new HashSet<E>();
for(E[] ary : arys) {
if(ary == null) continue;
for(E item : ary) {
if(item != null) hs.add(item);
}
}
hs.remove(null);
return hs.toArray((E[]) Array.newInstance(
arys.getClass().getComponentType(),hs.size()));
}
However when the code runs it generates this exception:
java.lang.ArrayStoreException: java.lang.String
at java.util.AbstractCollection.toArray(AbstractCollection.java:188)
at util.Utils.aryMergeNoDup(Utils.java:197)
The runtime type of the variable arys is String[]; however, when I replace arys.getClass().getComponentType() with String.class the code runs fine.
However, the method can only be used for Strings because pf this. I can't see what's going wrong, as they should both refer to java.lang.String.
The line in AbstractCollection.java:188 that throws the Exception is:
r[i] = (T)it.next();
public <T> T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) { // fewer elements than expected
if (a != r)
return Arrays.copyOf(r, i);
r[i] = null; // null-terminate
return r;
}
r[i] = (T)it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
Since it's a varargs, the runtime type of arys will be E[][], not E[]. Therefore you probably need arys.getClass().getComponentType().getComponentType() as the argument to Array.newInstance.
I believe the problem is that arys is something like an array of arrays. So probably arys.getClass().getComponentType() is String[], and not String.
You've got two separate things interacting here. First, you are using varargs, which under the covers wrap their arguments in an array generated on the fly. So the type of arys will be E[][], so get component type will be E[]. Second, generics mean that E is erased to Object at runtime, so even two getComponentType calls aren't going to cut it - unless you are OK with always returning Object[].
What you could do, is use the component type of arys[0], if it exists. This won't even work for all cases, since for example the type of the second array may be a superclass, or a sibling of the first, assignment incompatible with an array of the first type.
To solve this, you could calculate the least upper bound type by examining the types of all the arrays, but I think this is overkill versus "first type wins" if your typical usage will be arrays of the same type.

Java call a method in another method of the same class

First of all i have little experience in Java.
Getting to my question, I am implementing my own list with my own methods.
public class MyList<E> implements List<E>{
.....
One of this methods returns the size of my list
public int getSize(){
....
}
Then I have two other methods that would be more simple if I could somehow apply this method to my list. How so?
I have a method that has to compare if a given list is equal to this list
public boolean equals(Lista<E> list){
....
}
I had though about first comparing the size of both list, and if they don't match it returns false. if they do, it continues to compare each element. Is this possible? How would I applied getSize ? If this is not possible, i will just compare element by element.
My other method has to return an array of each element
public Object[] toArray() {
E myarray = new E[??]
As you can see, i dont' know how to declare this array. I would have to know beforehand the size of my list. I though about passing as an argument (which would solve the problem) but i need to solve it this way.
You call list.getSize(), like so:
if (list.getSize() != this.getSize()) {
return false;
}
Since you cannot create generic array in Java, you would have to do
public Object[] toArray() {
E[] myarray = (E[]) new Object[this.getSize()];
Simply use the getSize() method:
E myarray = new E[getSize()];

Java - Retrieving amount of types in list

I have a list. The list can contain multiple items of the same enum type.
Lets say i have an enum : TOY which has values: BALL, DOLL, PLAYSTATION. I want to know how many PLAYSTATION items are in a list with the type TOY. (ie, List<Toy> toys)
What is the best possible solution for this? I don't want to keep iterating through the list everytime.
You can use Apache commons-collections' HashBag. It has a getCount(Object) method which will suit you.
java.util.Collections has a method called frequency(Collection c, Object type).
Usage in my question:
int amountOfPlayStations = Collections.frequency(toys, TOY.PLAYSTATION);
Why don't you create a decorator for the type of list you're using which stores a list of counts for each enum type have been added/removed internally. That way you could use it as a normal list but also add some extra functionality for querying how many of which type are currently contained.
All you'd need to do would be to override the add/remove/addAll etc methods and increment your counters before passing it on to the real list type. The best part about it would be that you could decorate any list type with your new wrapper.
At the very least, a utility method like:
public int count(List<Toy> haystack, Toy needle) {
int result;
for (Toy t : haystack) {
if (t == needle) {
result++;
}
}
return result;
}
Would let you concisely refer to the number of PLAYSTATIONs from elsewhere in the code. Alternatively if you knew the list was unlikely to change, building a Map<Toy, Integer> would let you build up the counts for all items once.
If you don't want to have to iterate over the entire collection each time, another alternative would be to write a ForwardingList implementation. The main benefits of this over the HashBag suggestion are:
it supports generics
it implements the List interface, so you can pass it to any method that expects a List
There is a downside to this approach however, in that you have to write a bit of plumbing code to get it up and running.
Below is a quick example of how you could do it. Note that if you do this you should override all methods that add/delete from the list, otherwise you may end up in an inconsistent state:
import com.google.common.collect.ForwardingList;
public class CountingList<E> extends ForwardingList<E> {
private List<E> backingList = new LinkedList<E>();
private Map<E, Integer> countMap = new HashMap<E, Integer>();
#Override
protected List<E> delegate() {
return backingList;
}
#Override
public boolean add(E element) {
backingList.add(element);
if(countMap.containsKey(element)) {
countMap.put(element, countMap.get(element) + 1);
} else {
countMap.put(element, 1);
}
return true;
}
public int getCount(E element) {
Integer count = countMap.get(element);
return count != null ? count.intValue() : 0;
}
}
Extend java.util.List method and override all mutator methods, i.e. the ones that are used for add or delete elements and also ones used to clear the list. Add a reference to a private java.util.Map which will hold the number of items per type. Add accessor methods which will return current number of elements per type.
The HashBag (by Bozho) seems to be your best bet. But a bit more general would be Googles Collections 2 with an appropriate Predicate:
List<Toy> toys;
List<Toy> playstations = Collections2.filter( toys, new Predicate() {
boolean apply(TOY toy){
return toy == TOY.PLAYSTATION;
}
});
Besides all those solutions (I have a weakness for the Collections.Frequency call), i would recommend you to take a look at google collections, and particularly to [Collections2.transform][2], which could give you a live view on items.
[2]: http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Collections2.html#transform(java.util.Collection, com.google.common.base.Function)

Categories

Resources