Java array of Hashtables - java

I need an array of Hashtables in a program that is storing all words from a given set of documents.
Index 1 of the array holds a hashtable of String -> Double which stores a word, and its count for document 1 (array index 100 = document number 100's hashtable).
I dont need help using this data structure, just in creating it.
I declare the Hashtable Array as follows:
Hashtable<String,Double>[] h1 = new Hashtable<String,Double>[];
... but this does not compile.
(NOTE: The Double is necessary rather than an Integer in the above declaration for later usage.)
QUESTION:
How do you create an array of hashtables which stores String->Double ???
Any suggestions appreciated guys....

... but this does not compile.
That's because the array has no name, new expects a number of elements and you can't just allocate an array of generics. Prefer a List instead:
List<Hashtable<String,Double>> wordCountPerDoc
= new ArrayList<Hashtable<String,Double>>();

just use
#SuppressWarnings("unchecked")
Hashtable<String,Double>[] h = (Hashtable<String,Double>[])new Hashtable<?,?>[10];
h[0] = new Hashtable<String, Double>();

why don't you use a Map<Integer, Map<String, Double> > ?
this way you don't waste space for non-existing documents, and still get O(1) retrieval.

you can create like this.
Hashtable<String,Double>[] arr = new Hashtable[10];

Two things: you can't declare an array with the parameterized types like that; you have to imply declare it a new Hashtable[]. And you need to give the array a length.
Mixing arrays and Collections, although possible, tends to be confusing and lead to problems in my experience; also HashMap is generally preferred to Hashtable. So I would tend to prefer a List<Map<String, Double>> for this application.

The reasons why this is an error are covered in Angelika Langer's Generics FAQ: Can I create an array whose component type is a concrete parameterized type?
Can I create an array whose component type is a concrete parameterized type?
No, because it is not type-safe.
Arrays are covariant, which means that
an array of supertype references is a
supertype of an array of subtype
references. That is, Object[] is a
supertype of String[] and a string
array can be accessed through a
reference variable of type Object[].
Arrays and generics can have odd interactions (largely due to implementation compromises to support compatibility). You may be better off (as larsmans suggested) looking at a suitable collection type such as a List of Maps.

An array seems to be an unusual choice of structure here. Perhaps you should consider storing your hashtables in a List. It will dynamically resize for you if you don't know how many document you will have ahead of time. If you use an ArrayList, you will still have constant-time reads of random indeces (like an array.) I think it's much simpler than using an array, and you still get the generic type checking. If you choose a List, you syntax becomes:
List<Map<String,Double>> documentWordCounts = new ArrayList<Map<String,Double>>();
Or choose a LinkedList depending on what kind of read/write pattern you want.

For fixed size array:
Hashtable<String,Double>[] h1 = new Hashtable[]{new Hashtable< String,Double>(),new Hashtable< String,Double>(),new Hashtable< String,Double>()};

Related

Creating a Generic array without using Arraylist

In order to complete one of my Java assignments, I have to do what seems like the impossible.
I have to create a method that takes in different stuff and plugs it into an array. We don't necessarily know what is being put into the array and thus the array must be able to accept Strings, Double, Integer, etc...
Of course, the obvious solution would be to use ArrayList<E> (i.e. a generic array). However, that's partly the complication of the problem. We cannot use an ArrayList, only a regular array. As far as I can find, when creating an array its intake value must be declared. Which leads me to believe that this assignment is impossible (yet I doubt the teacher would give me an impossible assignment).
Any suggestions?
You can always use an array of Object - Object[].
Object[] objects = new Object[2];
objects[0] = "ABC";
objects[1] = Integer.valueOf("15");
Are you sure you need a generic array or an array that can hold anything?
If the former, then create a class that will act as wrapper of Object[] array and use a <T> generic for type cast when getting the elements of the array, which is similar to the implementation of ArrayList class. If the latter, use Object[] directly.

ArrayList construct and array of capacity?

Will
ArrayList<int>(20);
create a maximum of 20 array or is it an illegal syntax?
This will not compile since the element type cannot be a primitive. Use Integer instead.
new ArrayList<Integer>(20); will create a list backed by an array with an initial capacity of 20.
Perhaps you should read API documentation for ArrayList first.
You can create an ArrayList instance like this:
List<Integer> list = new ArrayList<Integer>(20);
In this case, 20 is initial capacity.
From Java7, you can omit the parameterized type.
List<Integer> list = new ArrayList<>(20);
You can't use primitive type as type parameter. Why don't Java Generics support primitive types? also helpful.
ArrayList<int>(20); is illegal, since you can't use primitives as generic types nor put them into the standard collections.
ArrayList<Integer>(20); would create a list with a basic capacity of 20 integer objects but it can be resized as needed.
Assuming that you change int to Integer (You can't use generics with primitives), that will create an ArrayList of initial size 20.
It can still grow past that limit, as per the JavaDocs at http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#ArrayList(int):
Constructs an empty list with the specified initial capacity.
If your question is about the memory allocation part and considering you use a syntax like:
ArrayList<Integer> arr = new ArrayList<Integer>(20);
It just allocates memory for 20 Integer. It still an empty ArrayList though.
This is intended to be used for performance reasons but for most common situation there isn't a big difference (without the memory preallocation that is).
Generally we should use the default constructor for any Collection object If we don't know the required size. Because think about the situation you are creating an ArrayList of size 500 but actually you are adding only 5 items into it. That is not recommended.
We can not use primitives in Generics for type safety in Collections. This restriction is for providing backward compatibility to older version java codes(Older than 1.5).
For more details kindly have a look here: Link 1, Link 2, Link 3, Link 5

Why do you need to specify an array to Set.toArray, which returns an array?

I'm confused about the design and proper use of toArray(T[]) method in Set (and other collections). If I have a Set of String, why do I need to specify an array of String of size 0, if the method is going to allocate a new String array anyway?
Set<String> stringSet = new Set<String>();
// bla bla bla, insert Strings to set
String[] array = stringSet.toArray(new String[0]);
Is there a better way to just get the array without allocating extra arrays or the explicit type conversion?
The parameter is used to detect the type of the array that's going to be created.
You could argue, why doesn't the JVM use the generic type parameter of the stringSet to detect the type. The answer is that at runtime the generic type parameter is not known due to type erasure, i.e Set<String> becomes Set after compilation.
toArray(new Object[0]) is identical in function to toArray().
If the set fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this set.
If you are using a collection, you may not know the exact number of entries that your set (or any other collection) will have. If you know from the beginning the number of entries, why don't you use an array instead of a collection?
The way I see it, the toArray() method is a simple way to create arrays using a collection for which you don't know a priori how many entries it will have.

Using Java List when array is enough

Is it advisable to use Java Collections List in the cases when you know the size of the list before hand and you can also use array there? Are there any performance drawbacks?
Can a list be initialised with elements in a single statement like an array (list of all elements separated by commas) ?
Is it advisable to use Java Collections List in the cases when you know the size of the list before hand and you can also use array there ?
In some (probably most) circumstances yes, it is definitely advisable to use collections anyway, in some circumstances it is not advisable.
On the pro side:
If you use an List instead of an array, your code can use methods like contains, insert, remove and so on.
A lot of library classes expect collection-typed arguments.
You don't need to worry that the next version of the code may require a more dynamically sized array ... which would make an initial array-based approach a liability.
On the con side:
Collections are a bit slower, and more so if the base type of your array is a primitive type.
Collections do take more memory, especially if the base type of your array is a primitive type.
But performance is rarely a critical issue, and in many cases the performance difference is not relevant to the big picture.
And in practice, there is often a cost in performance and/or code complexity involved in working out what the array's size should be. (Consider the hypothetical case where you used a char[] to hold the concatenation of a series. You can work out how big the array needs to be; e.g. by adding up the component string sizes. But it is messy!)
Collections/lists are more flexible and provide more utility methods. For most situations, any performance overhead is negligible.
And for this single statement initialization, use:
Arrays.asList(yourArray);
From the docs:
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray. The returned list is serializable and implements RandomAccess.
My guess is that this is the most performance-wise way to convert to a list, but I may be wrong.
1) a Collection is the most basic type and only implies there is a collection of objects. If there is no order or duplication use java.util.Set, if there is possible duplication and ordering use java.util.List, is there is ordering but no duplication use java.util.SortedSet
2) Curly brackets to instantiate an Array, Arrays.asList() plus generics for the type inference
List<String> myStrings = Arrays.asList(new String[]{"one", "two", "three"});
There is also a trick using anonymous types but personally I'm not a big fan:
List<String> myStrings = new ArrayList<String>(){
// this is the inside of an anonymouse class
{
// this is the inside of an instance block in the anonymous class
this.add("one");
this.add("two");
this.add("three");
}};
Yes, it is advisable.
Some of the various list constructors (like ArrayList) even take arguments so you can "pre-allocate" sufficient backing storage, alleviating the need for the list to "grow" to the proper size as you add elements.
There are different things to consider: Is the type of the array known? Who accesses the array?
There are several issues with arrays, e.g.:
you can not create generic arrays
arrays are covariant: if A extends B -> A[] extends B[], which can lead to ArrayStoreExceptions
you cannot make the fields of an array immutable
...
Also see, item 25 "Prefer lists to arrays" of the Effective Java book.
That said, sometimes arrays are convenient, e.g. the new Object... parameter syntax.
How can a list be initialised with elements in a single statement like an array = {list of all elements separated by commas} ?
Arrays.asList(): http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html#asList%28T...%29
Is it advisable to use Java Collections List in the cases when you know the size of the list before hand and you can also use array there ? Performance drawbacks ???
If an array is enough, then use an array. Just to keep things simple. You may even get a slightly better performance out of it. Keep in mind that if you...
ever need to pass the resulting array to a method that takes a Collection, or
if you ever need to work with List-methods such as .contains, .lastIndexOf, or what not, or
if you need to use Collections methods, such as reverse...
then may just as well go for the Collection/List classes from the beginning.
How can a list be initialised with elements in a single statement like an array = {list of all elements separated by commas} ?
You can do
List<String> list = Arrays.asList("foo", "bar");
or
List<String> arrayList = new ArrayList<String>(Arrays.asList("foo", "bar"));
or
List<String> list = new ArrayList<String>() {{ add("foo"); add("bar"); }};
Is it advisable to use Java
Collections List in the cases when you
know the size of the list before hand
and you can also use array there ?
Performance drawbacks ?
It can be perfectly acceptable to use a List instead of an array, even if you know the size before hand.
How can a list be initialised with
elements in a single statement like an
array = {list of all elements
separated by commas} ?
See Arrays.asList().

java: how can I create a dynamic array without forcing the type of the values?

I need to create a dynamic array in Java, but the values type differ from String to Int to float. how can I create a dynamic list that I don't need to give it in advanced the type of the values?
The keys just need to be ascending numbers (1,2,3,4 or 0,1,2,3,4)
I checked ArrayList but it seems that I have to give it a fixed type for the values.
thanks!
You can have an array or an ArrayList of Objects which will allow you to contain String, int, and float elements.
You can use this:
List<Object> myList = new ArrayList<Object>();
Integer i = 1;
Double d = 1.2;
String s = "Hello World";
myList.add(i);
myList.add(d);
myList.add(s);
It's pretty rare, in my experience, to want a List<Object>. I think it might be a design smell, and I'd examine the design to see if another set of structures might better represent your data. Without knowing anything about what you're trying to solve, it's hard to say with any confidence, but typically one wants to do things with what one has put into a list, and to do anything meaningful with things once they're just Object, you'll need to examine their type and get reflective, to kind of break away from language basics. Versus storing them in more type-sensitive structures, where you can deal directly with them in their original types without reflection magic.
It's more trouble than it's worth, but it is possible to interact with arrays reflectively.
import java.lang.reflect.Array;
// ...
Object arr = Array.newInstance(int.class, 10);
System.out.println(arr.getClass().getName()); // prints "[I"
System.out.println(Array.getLength(arr)); // prints "10"
Array.set(arr, 5, 42);
if (arr instanceof int[]) {
int[] nums = (int[]) arr;
System.out.println(nums[5]); // prints "42"
}
References
java.lang.reflect.Array API
Do note that in the API you pass arrays as Object. This is because Object is the superclass of all array types, be it int[].class or String[][].class. This also means that there is little compile time safety (as is true with reflection in general). Array.getLength("mamamia") compiles just fine; it'll throw an IllegalArgumentException at runtime.

Categories

Resources