How to implement a fixed size "list" in Java?
Solution 1
I'd write a wrapper class around an ArrayList
, and in the add
and addAll
methods, I'd check for the list's size before adding new elements. If you have reached the maximum size, you can then throw an exception (or do nothing, depending on what you really want to do in your code).
Here's a short example:
public class SizeLimitedArray<E> implements java.util.List<E>
{
private static final int DEFAULT_SIZE_LIMIT = 10;
private ArrayList<E> myList;
private int maxSize;
public SizeLimitedArray ()
{
this (DEFAULT_SIZE_LIMIT);
}
public SizeLimitedArray (int size)
{
myList = new ArrayList<E> (size);
maxSize = size;
}
@Override
public boolean add (E objectToAdd)
{
if (myList.size () > maxSize)
{
throw new IllegalStateException ("The array is full");
}
return myList.add (objectToAdd);
}
@Override
public boolean addAll (Collection collectionToAdd)
{
if (myList.size () + collectionToAdd.size () > maxSize)
{
throw new IllegalStateException ("The array is full");
}
return myList.addAll (collectionToAdd);
}
// Rest of class omitted for brevity
}
Solution 2
Arrays.asList(T ...) Returns a fixed-size list backed by the specified array
Object[] array = new Object[10];
List<Object> fixedList = Arrays.asList(array);
Solution 3
You could use an array, or an ArrayList<E>
pre-initialized with the desired size.
If you want to actively prevent the expansion of the list, then using an array is probably the easiest.
Solution 4
Just implement your own. You could use a proxy-based approach. Define your own list that is backed by an ArrayList
. Make the internal list private. Also implement a simple limit
field that has a default and also can be set via a constructor.
Your list will implement List
, and for every method that modifies the internal list, increment and decrements the count appropriately. If the size exceeds the limit, throw some sort of exception. Something like
public class FixedList implements List {
private ArrayList<E> list = new ArrayList<E>();
private int limit = 10; // default
FixedList(){} // default constructor
FixedList(int limit) {
this.limit = limit;
}
public boolean add(E object) {
if (this.list.size() == limit - 1) {
// throw some sort of LimitExceeded Runtime Exception
}
this.list.add(object);
}
...
}
You will have to work on the generics, and remember to support the cases where multiple things are added at once addAll
.
Solution 5
Well you could inherit from class ArrayList
for example and reimplement the add
method to not be able to add past a given amount of elements. Or, even better as pointer out by Laf, use composition:
public class MyArrayList<T> {
private ArrayList<T> innerList;
private int maxSize;
public boolean add(T item) {
if(innerList.size() < maxSize) {
return innerList.add(item);
} else {
return false;
}
}
}
mre
Updated on July 28, 2022Comments
-
mre almost 2 years
Since the Java core library doesn't have such a collection, would an array be the best option, especially if one doesn't want to rely on third-party libraries?
-
mre over 12 yearsBut if I add an object to the
ArrayList
instance that would cause it to exceed its size, won't it automatically expand? -
NPE over 12 years@mre: If you do, it will. Are you saying you want to actively prevent yourself from doing this?
-
mre over 12 years@aix, Yes, I want to actively prevent myself from doing this.
-
mre over 12 yearsThat's kind-of where I was thinking I'd have to go if I didn't want to use an array.
-
Laf over 12 yearsI wouldn't recommend inheritance in this case, but a wrapper class. Overriding the
add
method might create more problems, because you become dependent of theArrayList
implementation. This is something Josh Bloch mentions in his Effective Java book. -
NPE over 12 years@mre: Fair enough. In that case, I personally would stick with an array.
-
Tudor over 12 years@mre: I've posted an example.
-
mre over 12 yearsSo, if I attempt to add another object to
fixedList
which already contains 10 objects, will it throw an exception or just silently fail? -
Aviram Segal over 12 yearsadd will give you UnsupportedOperationException, you can only use set and get, basically behaves like an array.
-
Voo over 12 yearsSo we take an
ArrayList
that was implemented to allow us to extend the size of arrays dynamically and then change its behavior so we can't do that anymore? Well yesnot not x
is the same asx
, but that's rather pointless isn't it? -
hvgotcodes over 12 yearsI'm not sure what your point is. Are you saying his custom list should be backed by an array instead?
-
Aviram Segal over 12 yearsOverkill, this is pretty much what Arrays.asList implements itself
-
Voo over 12 yearsWell, you removed all additional functionality that
ArrayList
added over a simple array, so we could just use the array itself - or if we need the add and co functions yes just backing it up by an array would be simpler too. -
hvgotcodes over 12 yearsyeah that's a valid approach, although I disagree what I've "removed all additional functionality...". I personally would use a List over an array because I don't want to have to maintain the pointer to the current index and all that, and also for generics, but OP could use an array if it suits his purposes.
-
Rob Hruska over 12 yearsIt doesn't offer access to all list methods, though (i.e. it doesn't implement any sort of list) - particularly index-based accessing methods, which (for me anyway) would be the main reason to be using a list in the first place.
-
Perception over 12 yearsTrue, I updated my answer to reflect that it really implements Collection operations, not List.