Is there an expandable list of object references in Java? - java

In Java, we can always use an array to store object reference. Then we have an ArrayList or HashTable which is automatically expandable to store objects. But does anyone know a native way to have an auto-expandable array of object references?
Edit: What I mean is I want to know if the Java API has some class with the ability to store references to objects (but not storing the actual object like XXXList or HashTable do) AND the ability of auto-expansion.

Java arrays are, by their definition, fixed size. If you need auto-growth, you use XXXList classes.
EDIT - question has been clarified a bit
When I was first starting to learn Java (coming from a C and C++ background), this was probably one of the first things that tripped me up. Hopefully I can shed some light.
Unlike C++, Object arrays in Java do not store objects. They store object references.
In C++, if you declared something similar to:
String myStrings[10];
You would get 10 String objects. At this point, it would be perfectly legal to do something like println(myStrings[5].length); - you'd get '0' - the default constructor for String creates an empty string with length 0.
In Java, when you construct a new array, you get an empty container that can hold 10 String references. So the call:
String[] myStrings = new String[10];
println(myStringsp[5].length);
would throw a null pointer exception, because you haven't actually placed a String reference into the array yet.
If you are coming from a C++ background, think of new String[10] as being equivalent to new (String *)[10] from C++.
So, with that in mind, it should be fairly clear why ArrayList is the solution for an auto expanding array of objects (and in fact, ArrayList is implemented using simple arrays, with a growth algorithm built in that allocates new expanded arrays as needed and copies the content from the old to the new).
In practice, there are actually relatively few situations where we use arrays. If you are writing a container (something akin to ArrayList, or a BTree), then they are useful, or if you are doing a lot of low level byte manipulation - but at the level that most development occurs, using one of the Collections classes is by far the preferred technique.

All the classes implementing Collection are expandable and store only references: you don't store objects, you create them in some data space and only manipulate references to them, until they go out of scope without reference on them.
You can put a reference to an object in two or more Collections. That's how you can have sorted hash tables and such...

What do you mean by "native" way? If you want an expandable list f objects then you can use the ArrayList. With List collections you have the get(index) method that allows you to access objects in the list by index which gives you similar functionality to an array. Internally the ArrayList is implemented with an array and the ArrayList handles expanding it automatically for you.

Straight from the Array Java Tutorials on the sun webpage:
-> An array is a container object that holds a fixed number of values of a single type.
Because the size of the array is declared when it is created, there is actually no way to expand it afterwards. The whole purpose of declaring an array of a certain size is to only allocate as much memory as will likely be used when the program is executed. What you could do is declare a second array that is a function based on the size of the original, copy all of the original elements into it, and then add the necessary new elements (although this isn't very 'automatic' :) ). Otherwise, as you and a few others have mentioned, the List Collections is the most efficient way to go.

In Java, all object variables are references. So
Foo myFoo = new Foo();
Foo anotherFoo = myFoo;
means that both variables are referring to the same object, not to two separate copies. Likewise, when you put an object in a Collection, you are only storing a reference to the object. Therefore using ArrayList or similar is the correct way to have an automatically expanding piece of storage.

There's no first-class language construct that does that that I'm aware of, if that's what you're looking for.

It's not very efficient, but if you're just appending to an array, you can use Apache Commons ArrayUtils.add(). It returns a copy of the original array with the additional element in it.

if you can write your code in javascript, yes, you can do that. javascript arrays are sparse arrays. it will expand whichever way you want.
you can write
a[0] = 4;
a[1000] = 434;
a[888] = "a string";

Related

Purpose of new keyword in creating array in Java

I want to know why an array created in Java static even when we use the new keyword to define it.
From what I've read, the new keyword allocates a memory space in the heap whenever it is encountered during run time, so why give the size of the array at all during definition.
e.g. Why can't
int[] array1=new int[20];
simply be:
int[] array1=new int[];
I know that it does not grow automatically and we have ArrayList for that but then what is the use of keyword new in this? It could have been defined as int array1[20]; like we used to do it in C, C++ if it has to be static.
P.S. I know this is an amateurish question but I am an amateur, I tried to Google but couldn't find anything comprehensive.
This may be an amateurish question, but it is one of the best amateurish questions you could make.
In order for java to allow you to declare arrays without new, it would have to support an additional kind of data type, which would behave like a primitive in the sense that it would not require allocation, but it would be very much unlike a primitive in the sense that it would be of variable size. That would have immensely complicated the compiler and the JVM.
The approach taken by java is to provide the bare minimum and sufficient primitives in order to be able to get most things done efficiently, and let everything else be done using objects. That's why arrays are objects.
Also, you might be a bit confused about the meaning of "static" here. In C, "static" means "of file scope", that is, not visible by other object files. In C++ and in Java, "static" means "belongs to the class" rather than "belongs to instances of the class". So, the term "static" is not suitable for describing array allocation. "Fixed size" or "fixed, predefined size" would be more suitable terms.
Well, in Java everything is an object, including arrays (they have length and other data). Thats why you cannot use
int var[20];
In java that would be an int and the compiler would be confused. Instead by using this:
int[] var;
You are declaring that var is of type int[] (int array) so Java understands it.
Also in java the length of the array and other data are saved on the array, for this reason you don't have to declare size of array during declaration, instead when creating an array (using new) the data are saved.
Maybe there is a better reason that oracle may have answered already, but the fact that in Java everything is an object must have something to do with it. Java is quite specific about objects and types, unlike C where you have more freedom but everything is more loose (especially using pointers).
The main idea of the array data structure is that all its elements are located in the sequential row of memory cells. That is why you can not create array with variable size: it should be unbounbed space vector in memory for this purpose, which is impossible.
If you want change size of array, you should recreate it.
Since arrays are fixed-size they need to know how much memory to allocate at the time they are instantiated.
ArrayLists or other resizing data structures that internally use arrays to store data actually re-allocate larger arrays when their inner array data
structure fills up.
My understanding of OP's reasoning is:
new is used for allocating dynamic objects (which can grow like, ArrayList), but arrays are static (can't grow). So one of them is unnecessary: the new or the size of the array.
If that is the question, then the answer is simple:
Well, in Java new is necessary for every Object allocation, because in Java all objects are dynamically allocated.
Turns out that in Java, arrays are objects, different from C/C++ where they are not.
All of Java's variables are at most a single 64bit field. Either primitives like
integer (32bit)
long (64bit)
...
or references to Objects which depending on JVM / config / OS are 64 or 32 bit fields (but unlike 64bit primitives with atomicity guaranteed).
There is no such thing as C's int[20] "type". Neither is there C's static.
What int[] array = new int[20] boils down to is roughly
int* array = malloc(20 * sizeof(java_int))
Each time you see new in Java you can imagine a malloc and a call to the constructor method in case it's a real Object (not just an array). Each Object is more or less just a struct of a few primitives and more pointers.
The result is a giant network of relatively small structs pointing to other things. And the garbage collector's task is to free all the leaves that have fallen off the network.
And this is also the reason why you can say Java is copy by value: both primitives and pointers are always copied.
regarding static in Java: there is conceptually a struct per class that represents the static context of a class. That's the place where static instance variables are anchored. Non-static instance variables are anchored at with their own instance-struct
class Car {
static int[] forAllCars = new int[20];
Object perCar;
}
...
new Car();
translates very loosely (my C is terrible) to
struct Car-Static {
Object* forAllCars;
};
struct Car-Instance {
Object* perCar;
};
// .. class load time. Happens once and this is referenced from some root object so it can't get garbage collected
struct Car-Static *car_class = (struct Car-Static*) malloc(sizeof(Car-Static));
car_class->forAllCars = malloc(20 * 4);
// .. for every new Car();
struct Car-Instance *new_reference = (struct Car-Instance*) malloc(sizeof(Car-Instance));
new_reference.perCar = NULL; // all things get 0'd
new_reference->constructor();
// "new" essentially returns the "new_reference" then

How do I know whether to use an array or an arraylist?

What determines whether one should be used over the other?
I used to think that the deciding factor is whether you know the size of the things you want to store but I think there might be more to it than that.
Some more differences:
First and Major difference between Array and ArrayList in Java is that Array is a fixed length data structure while ArrayList is a variable length Collection class. You can not change length of Array once created in Java but ArrayList re-size itself when gets full depending upon capacity and load factor. Since ArrayList is internally backed by Array in Java, any resize operation in ArrayList will slow down performance as it involves creating new Array and copying content from old array to new array.
Another difference between Array and ArrayList in Java is that you can not use Generics along with Array, as Array instance knows about what kind of type it can hold and throws ArrayStoreException, if you try to store type which is not convertible into type of Array. ArrayList allows you to use Generics to ensure type-safety.
One more major difference between ArrayList and Array is that, you can not store primitives in ArrayList, it can only contain Objects. While Array can contain both primitives and Objects in Java. Though Autoboxing of Java 5 may give you an impression of storing primitives in ArrayList, it actually automatically converts primitives to Object.
Java provides add() method to insert element into ArrayList and you can simply use assignment operator to store element into Array e.g. In order to store Object to specified position.
One more difference on Array vs ArrayList is that you can create instance of ArrayList without specifying size, Java will create Array List with default size but its mandatory to provide size of Array while creating either directly or indirectly by initializing Array while creating it. By the way you can also initialize ArrayList while creating it.
Use array when you know the exact size of the collection and you don't expect to add/remove elements.
Use List (ArrayList) when you don't know the exact size of the collection and you expect to alter it at some point.
If you're using Java8, there is the Stream API, which helps to significantly reduce the boilerplate code when working with collections. This is another plus for ArrayList (and all Collections and Maps).
More info:
Arrays vs ArrayList in performance
Unless speed is critical (really critical, like every microsecond counts), use ArrayList whenever possible. It's so much easier to use, and that's usually the most important thing to consider.
Generally, I use ArrayList, not arrays, because they offer a lot of several methods that are very usefull. I think you can use array if performance is very important, in very special cases.
Array is fixed, ArrayList is growable.If the number of elements is fixed, use an array
Also one of the great benefits of collection implementations is they give you a lot of flexibility. So depending on your need, you can have a List behave as an ArrayList or as a LinkedList and so on. Also if you look at the Collection API, you'd see you have methods for almost everything you'd ever need to do.

Are there reasons to prefer Arrays over ArrayLists? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Benefits of arrays
Hey there,
are there any reasons to prefer Arrays (MyObject[]) over ArrayLists (List<MyObject>)? The only left place to use Arrays is for primitive data types (int, boolean, etc.). However I have no reasonable explanation for this, it just makes the code a little bit slimmer.
In general I use List in order to maintain a better flexibility. But are there reasons left to use real Arrays?
I would like to know,
best regards
I prefer to use Arrays over ArrayLists whenever I know I am only going to work with a fixed number of elements. My reasons are mostly subjective, but I'm listing them here anyway:
Using Collection classes for primitives is appreciably slower since they have to use autoboxing and wrappers.
I prefer the more straightforward [] syntax for accessing elements over ArrayList's get(). This really becomes more important when I need multidimensional arrays.
ArrayLists usually allocate about twice the memory you need now in advance so that you can append items very fast. So there is wastage if you are never going to add any more items.
(Possibly related to the previous point) I think ArrayList accesses are slower than plain arrays in general. The ArrayList implementation uses an underlying array, but all accesses have to go through the get(), set(), remove(), etc. methods which means it goes through more code than a simple array access. But I have not actually tested the difference so I may be wrong.
Having said that, I think the choice actually depends on what you need it for. If you need a fixed number of elements or if you are going to use multiple dimensions, I would suggest a plain array. But if you need a simple random access list and are going to be making a lot of inserts and removals to it, it just makes a lot more sense to use an Arraylist
Generally arrays have their problems, e.g. type safety:
Integer[] ints = new Integer[10];
Number[] nums = ints; //that shouldn't be allowed
nums[3] = Double.valueOf[3.14]; //Ouch!
They don't play well with collections, either. So generelly you should prefer Collections over arrays. There are just a few things where arrays may be more convenient. As you already say primitive types would be a reason (although you could consider using collection-like libs like Trove). If the array is hidden in an object and doesn't need to change its size, it's OK to use arrays, especially if you need all performance you can get (say 3D and 4D Vectors and Matrices for 3D graphics). Another reason for using arrays may be if your API has lots of varargs methods.
BTW: There is a cute trick using an array if you need mutable variables for anonymous classes:
public void f() {
final int[] a = new int[1];
new Thread(new Runnable() {
public void run() {
while(true) {
System.out.println(a[0]++);
}
}
}).start();
}
Note that you can't do this with an int variable, as it must be final.
I think that the main difference of an array and a list is, that an array has a fixed length. Once it's full, it's full. ArrayLists have a flexible length and do use arrays to be implemented. When the arrayList is out of capacity, the data gets copied to another array with a larger capacity (that's what I was taught once).
An array can still be used, if you have your data length fixed. Because arrays are pretty primitive, they don't have much methods to call and all. The advantage of using these arrays is not so big anymore, because the arrayLists are just good wrappers for what you want in Java or any other language.
I think you can even set a fixed capacity to arraylists nowadays, so even that advantage collapses.
So is there any reason to prefer them? No probably not, but it does make sure that you have just a little more space in your memory, because of the basic functionality. The arraylist is a pretty big wrapper and has a lot of flexibility, what you do not always want.
one for you:
sorting List (via j.u.Collections) are first transformed to [], then sorted (which clones the [] once again for the merge sort) and then put back to List.
You do understand that ArrayList has a backing Object[] under the cover.
Back in the day there was a case ArrayList.get was not inlined by -client hotspot compiler but now I think that's fixed. Thus, performance issue using ArrayList compared to Object[] is not so tough, the case cast to the appropriate type still costs a few clocks (but it should be 99.99% of the times predicted by the CPU); accessing the elements of the ArrayList may cost one more cache-miss more and so (or the 1st access mostly)
So it does depend what you do w/ your code in the end.
Edit
Forgot you can have atomic access to the elements of the array (i.e. CAS stuff), one impl is j.u.c.atomic.AtomicReferenceArray. It's not the most practical ones since it doesn't allow CAS of Objec[][] but Unsafe comes to the rescue.

How to initialize a dynamic array in java?

If I have a class that needs to return an array of strings of variable dimension (and that dimension could only be determined upon running some method of the class), how do I declare the dynamic array in my class' constructor?
If the question wasn't clear enough,
in php we could simply declare an array of strings as $my_string_array = array();
and add elements to it by $my_string_array[] = "New value";
What is the above code equivalent then in java?
You will want to look into the java.util package, specifically the ArrayList class. It has methods such as .add() .remove() .indexof() .contains() .toArray(), and more.
Plain java arrays (ie String[] strings) cannot be resized dynamically; when you're out of room but you still want to add elements to your array, you need to create a bigger one and copy the existing array into its first n positions.
Fortunately, there are java.util.List implementations that do this work for you. Both java.util.ArrayList and java.util.Vector are implemented using arrays.
But then, do you really care if the strings happen to be stored internally in an array, or do you just need a collection that will let you keep adding items without worrying about running out of room? If the latter, then you can pick any of the several general purpose List implementations out there. Most of the time the choices are:
ArrayList - basic array based implementation, not synchronized
Vector - synchronized, array based implementation
LinkedList - Doubly linked list implementation, faster for inserting items in the middle of a list
Do you expect your list to have duplicate items? If duplicate items should never exist for your use case, then you should prefer a java.util.Set. Sets are guaranteed to not contain duplicate items. A good general-purpose set implementation is java.util.HashSet.
Answer to follow-up question
To access strings using an index similar to $my_string_array["property"], you need to put them in a Map<String, String>, also in the java.util package. A good general-purpose map implementation is HashMap.
Once you've created your map,
Use map.put("key", "string") to add strings
Use map.get("key") to access a string by its key.
Note that java.util.Map cannot contain duplicate keys. If you call put consecutively with the same key, only the value set in the latest call will remain, the earlier ones will be lost. But I'd guess this is also the behavior for PHP associative arrays, so it shouldn't be a surprise.
Create a List instead.
List<String> l = new LinkedList<String>();
l.add("foo");
l.add("bar");
No dynamic array in java, length of array is fixed.
Similar structure is ArrayList, a real array is implemented underlying it.
See the name ArrayList :)

When is an ArrayList preferable to an array in Java?

When should I use an ArrayList in Java, and when should I use an array?
Some differences:
Arrays are immutable in their size, you cannot easly remove and element and remove the hole whereas using an ArrayList is straightforward
Arrays are fast (handled directly by the JVM as special objects) than an ArrayList and requires less memory
Arrays have a nice syntax for accessing elements (e.g. a[i] vs a.get(i))
Arrays don't play well with generics (e.g. you cannot create a generic array)
Arrays cannot be easly wrapped as ArrayList (e.g. Collections utils like checkedList, synchronizedList and unmodifiableList)
declaring the ArrayList as List you can easly swap implementation with a LinkedList when you need; this imho is the best advantage over plain arrays
Array's toString, equals and hashCode are weird and error-prone, you must use Arrays class utilities
Another couple of points:
You may want to consider using an array to represent more than one dimension (e.g. matrix).
Arrays can be used to store primitives and hence offer a more compact representation of your data than using an ArrayList.
ArrayLists are useful when you don't know in advance the number of elements you will need. Simple Example: you are reading a text file and builing a list of all the words you find. You can just keep adding to your array list, it will grow.
Arrays you need to pre-declare their size.
It's not only about the fact that arrays need to grow, a collection is easier to deal with.
Sometimes arrays are fine, when you just need to iterate over elements, read-only. However, most of the time you want to use methods like contains, etc.
You can't create generic arrays so it 'might' or might not bother you.
When in doubt, use Collections, it will make people that use your API love you :-). If you only provide them with arrays, the first lines of code that they'll write is :
Arrays.asList(thatGuyArray);
The List interface, of which ArrayList is an implementation in the Java Collections Framework is much richer then what a plain Java array has to offer. Due to the relatively widespread support of the collection framework throughout Java and 3rd party libraries, using an ArrayList instead of an array makes sense in general. I'd only use arrays if there is really need for them:
They are required by some other interface I'm calling
Profiling shows a bottleneck in a situation where array access can yield a significant speedup over list access
Situations where an array feels more natural such as buffers of raw data as in
byte[] buffer = new byte[0x400]; // allocate 1k byte buffer
You can always get an array representation of your ArrayList if you need one:
Foo[] bar = fooList.toArray(new Foo[fooList.size()])
It is a common failure pattern that methods return a reference to a private array member (field) of a class. This breaks the class' encapsulation as outsiders gain mutable access to the class' private state. Consequently you would need to always clone the array and return a reference to the cloned array. With an ArrayList you can use...
return Collections.unmodifiableList(privateListMember);
... in order to return a wrapper that protects the actual list object. Of course you need to make sure that the objects in the list are immutable too, but that also holds for a (cloned) array of mutable objects.
As per Nick Holt's comment, you shouldn't expose the fact that a List is an ArrayList anywhere:
private List<Foo> fooList = new ArrayList<Foo>();
public List<Foo> getFooList() {
return Collections.unmodifiableList(fooList);
}
An array has to be declared with a fixed size therefore you need to know the number of elements in advance.
An ArrayList is preferable when you don't know how many elements you will need in advance as it can grow as desired.
An ArrayList may also be preferable if you need to perform operations that are available in its API that would required manual implementation for an array. (e.g. indexOf)
When you want to change its size by adding or removing elements.
When you want to pass it to something that wants a Collection or Iterable (although you can use Arrays.asList(a) to make an array, a, look like a List).
I would say the default presumption should be to use an ArrayList unless you have a specific need, simply because it keeps your code more flexible and less error prone. No need to expand the declaration size when you add an extra element 500 lines of code away, etc. And reference the List interface, so you can replace the Array list with a LinkedList or a CopyOnWriteArrayList or any other list implementation that may help a situation without having to change a lot of code.
That being said, arrays have some properties that you just won't get out of a list. One is a defined size with null elements. This can be useful if you don't want to keep things in a sequential order. For example a tic-tac-toe game.
Arrays can be multi-dimensional. ArrayLists cannot.
Arrays can deal with primitives, something an ArrayList cannot (although there are third party collection classes that wrap primitives, they aren't part of the standard collections API).
G'day,
A couple of points that people seem to have missed so far.
an array can only contain one type of object whereas an ArrayList is a container that can contain a mixture of object types, it's heterogeneous,
an array must declare the type of its contents when the array itself is declared. An ArrayList doesn't have to declare the type of its contents when the ArrayList is declared,
you must insert an item into a specific location in an array. Adding to an ArrayList is done by means of the add() method on the container, and
objects are stored in an array and retain their type because of the way the array can only store objects of a particular type. Objects are stored in an ArrayList by means of the superclass type Object.
Edit: Ooop. Regarding the last point on the list, I forgot the special case where you have an array of Objects then these arrays can also contain any type of object. Thanks for the comment, Yishai! (-:
HTH
cheers,

Categories