5

I have this:

private ArrayList<ArrayList<Object>> models;

and in the constructor I have:

models = new ArrayList<ArrayList<Object>>();

Later, I do things like:

models.add(new ArrayList<Object>());

as well as other operations.

I want to make the external ArrayList to something with a fixed size (Array, List) and I am really lost to how I am going to write the declaration, initialization, addition, etc. because of the nested objects. Can someone save me time by answering this for me?

John
  • 359
  • 4
  • 19

3 Answers3

6

You can use Arrays.asList() to created fixed sized Lists.

Examples:

A List of size 3, initialized with null values:

List<ArrayList<Object>> models = Arrays.asList (null,null,null);

A List of size 3, initialized with non-null values:

List<ArrayList<Object>> models = Arrays.asList (new ArrayList<Object> (),new ArrayList<Object> (),new ArrayList<Object> ());

A List of size 10, initialized with null values:

List<ArrayList<Object>> models = Arrays.asList ((ArrayList<Object>[])new ArrayList[10]);

Note that add operation is not supported for fixed sized lists. You'll have to use models.set(index,new ArrayList<Object>()) instead.

EDIT:

Here's another way to initialize the List using Streams:

List<ArrayList<Object>> models = Arrays.asList (Stream.generate (ArrayList::new).limit (10).toArray (ArrayList[]::new));
Eran
  • 387,369
  • 54
  • 702
  • 768
  • Once you get the list from list, you won't be able to modify it. – Suresh Atta Jan 02 '18 at 10:33
  • @ꜱᴜʀᴇꜱʜᴀᴛᴛᴀ You can replace the elements (the same way you can replace elements in arrays), you just can't add or remove elements. – Eran Jan 02 '18 at 10:35
  • `you just can't add or remove elements.` yeah. That is what I am trying to say :( – Suresh Atta Jan 02 '18 at 10:35
  • @ꜱᴜʀᴇꜱʜᴀᴛᴛᴀ which is exactly what the OP requested - `I want to make the external ArrayList to something with a **fixed size**` – Eran Jan 02 '18 at 10:36
  • @ꜱᴜʀᴇꜱʜᴀᴛᴛᴀ That's was the OP was looking for. – Zachary Jan 02 '18 at 10:36
  • May be I am wrong. What I have understood is, He wants to declares list with some size X and then nobody else can add more than X size. – Suresh Atta Jan 02 '18 at 10:40
  • @Eran Is there any reason to use Varargs as opposed to Arrays.asList(new Object[size]) – Zachary Jan 02 '18 at 10:40
  • @Eran what I don't like about this, that once exposed all the user of this sees is a `List` - it has no idea that it's immutable. I would suggest to just declare it to be immutable - unfortunately only with a help of some external lib, like guava, `ImmutableList<...>` – Eugene Jan 02 '18 at 10:40
  • @Eran, can you please add code for when I have a fixed size of 10, to add it as: Arrays.asList (10 X new ArrayList () )? – John Jan 02 '18 at 10:41
  • 1
    @Zachary you can do something similar to what you suggested. I edited the answer. – Eran Jan 02 '18 at 10:42
  • I get this when I am creating initializing: "Type safety: Unchecked cast from ArrayList[] to ArrayList[]". Is it OK? – John Jan 02 '18 at 10:46
  • @JohnZobolas There's no way to avoid that, since you can't instantiate generic arrays. – Eran Jan 02 '18 at 10:47
  • @Eugene But the requirement is not for an ImmutableList. A fixed sized list is a different thing. – Eran Jan 02 '18 at 10:48
  • @JohnZobolas Please see my latest edit. When using a `Stream` to generate the array, I don't get a warning and I don't need the cast. – Eran Jan 02 '18 at 10:56
  • @Eran I will see it, thanks! So, I cannot add, remove, etc to the list, but to the `ArrayList` inside I can do it, correct? Like: `models.get(index).add(model)`; where model is `ArrayList` – John Jan 02 '18 at 11:00
  • @JohnZobolas Yes, you can only add/remove elements to/from the inner ArrayLists. Are you saying that the inner ArrayLists also contain ArrayLists? That's a complex structure. – Eran Jan 02 '18 at 11:02
  • @Eran, no more ArrayLists inside :) just objects of a generic type of a model I am using. Testing this now, later I will mark it as best answer! – John Jan 02 '18 at 11:07
2

A slightly more verbose - but generic-compatible way - of doing it is to extend AbstractList.

The methods you need to override are described in the Javadoc:

To implement an unmodifiable list, the programmer needs only to extend this class and provide implementations for the get(int) and size()methods.

To implement a modifiable list, the programmer must additionally override the set(int, E) method (which otherwise throws an UnsupportedOperationException).

So, implement these three methods, delegating to an ArrayList:

class FixedSizedList<T> extends AbstractList<T> {
  private final List<T> delegate;

  FixedSizedList(int size) {
    delegate = new ArrayList<>(Collections.nCopies(size, null));
  }

  public T get(int i) { return delegate.get(i); }
  public int size() { return delegate.size(); }
  public T set(int i, T e) { return delegate.set(i, e); }
}

Or, for that matter, just use an array:

class FixedSizedList<T> extends AbstractList<T> {
  private final Object[] array;

  FixedSizedList(int size) {
    array = new Object[size];
  }

  public T get(int i) { return (T) array[i]; }
  public int size() { return array.length; }
  public T set(int i, T e) {
    T old = (T) array[i];
    array[i] = e;
    return old;
  }
}
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • @Eugene no, it doesn't. That's the thing about extending `AbstractList`: it does the right thing for all the methods it doesn't ask you to override. – Andy Turner Jan 02 '18 at 10:44
  • @Eugene when can you ever add elements by throwing an exception? – Andy Turner Jan 02 '18 at 10:50
  • @Eugene it's a fixed-sized list: it never holds zero elements, unless you construct it to have zero elements. If you construct it with 10 elements, it stores 10 null elements initially. – Andy Turner Jan 02 '18 at 10:56
  • 1
    oh my! I completly missed the `Collections.nCopies(size, null)` inside the constructor. :| will remove the comments – Eugene Jan 02 '18 at 10:59
0

There isn't an Array class in java, but there is the plain old array declaration:

ArrayList<Object> [] array...

Problem is that you will not be able to instantiate it like this, since arrays can not be generic.

You are really looking for either Arrays.asList or much better ImmutableList of some kind.

Eugene
  • 117,005
  • 15
  • 201
  • 306