How to implement a fixed size "list" in Java?
Asked Answered
S

8

8

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?

Spavin answered 23/1, 2012 at 17:9 Comment(3)
What behavior do you want when you try to add an item to a full list? You should probably also have a method that checks if there is some space.Estus
Arrays.asList does exactly this.Ephah
The question is ambiguous: the list is fixed? or its size is fixed?Estus
S
4

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
    }
Sphingosine answered 23/1, 2012 at 17:16 Comment(0)
N
12

Arrays.asList(T ...) Returns a fixed-size list backed by the specified array

Object[] array = new Object[10];
List<Object> fixedList = Arrays.asList(array);
Newsboy answered 23/1, 2012 at 17:11 Comment(2)
So, if I attempt to add another object to fixedList which already contains 10 objects, will it throw an exception or just silently fail?Spavin
add will give you UnsupportedOperationException, you can only use set and get, basically behaves like an array.Newsboy
P
5

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.

Pratincole answered 23/1, 2012 at 17:11 Comment(5)
But if I add an object to the ArrayList instance that would cause it to exceed its size, won't it automatically expand?Spavin
@mre: If you do, it will. Are you saying you want to actively prevent yourself from doing this?Pratincole
@aix, Yes, I want to actively prevent myself from doing this.Spavin
@mre: Fair enough. In that case, I personally would stick with an array.Pratincole
Overkill, this is pretty much what Arrays.asList implements itselfNewsboy
S
4

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
    }
Sphingosine answered 23/1, 2012 at 17:16 Comment(0)
N
3

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.

Neusatz answered 23/1, 2012 at 17:13 Comment(4)
So 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 yes not not x is the same as x, but that's rather pointless isn't it?Bumpkin
I'm not sure what your point is. Are you saying his custom list should be backed by an array instead?Neusatz
Well, 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.Bumpkin
yeah 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.Neusatz
G
2

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;
         }
     }
}
Galina answered 23/1, 2012 at 17:12 Comment(3)
That's kind-of where I was thinking I'd have to go if I didn't want to use an array.Spavin
I wouldn't recommend inheritance in this case, but a wrapper class. Overriding the add method might create more problems, because you become dependent of the ArrayList implementation. This is something Josh Bloch mentions in his Effective Java book.Sphingosine
@mre: I've posted an example.Galina
O
0

Use Collections.unmodifiableList(List<T> list). This will return a generic List<T> object which throws UnsupportedOperationException if you attempt to add (or remove) elements.

Osburn answered 23/1, 2012 at 17:19 Comment(0)
T
0

I will probably get burned, but you can also use an ArrayBlockingQueue for this. Which provides the benefit of being able to use regular Collection methods.

Tetrasyllable answered 23/1, 2012 at 17:30 Comment(2)
It 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.Rootstock
True, I updated my answer to reflect that it really implements Collection operations, not List.Tetrasyllable
E
-1
 public class libsystem extends javax.swing.JFrame {

   //public static ArrayList<books> al = new ArrayList<books>();
   public static List<books> al = Arrays.asList(new books[100]);
   public libsystem() {
    initComponents();
  }
   String msg =jTextArea1.getText();

    try {
        FileWriter fs=new FileWriter("library.txt");
        try(
            BufferedWriter out= new BufferedWriter(fs)){;
            out.write(msg);
        }
       } catch (Exception e){
        System.err.println("wrong" + e.getMessage());                                
  }
    String line;
    String id,name,type;
    try{
        FileReader in=new FileReader("library.txt");
        try (BufferedReader br = new BufferedReader(in)) {      

            while((line=br.readLine())!=null){      
                StringTokenizer st1 = new StringTokenizer(line,",");    
                while(st1.hasMoreTokens()){     
                    id=st1.nextToken();     
                    name=st1.nextToken();    
                    type=st1.nextToken();   
      books book=new books(id,name,type);    
                al.add(book);     
              }     
                br.close();    
        for(int i=0;i<al.size();i++){    
      books obj = al.get(i);    

        System.out.println("Book NAme :"+obj.getName()+ "\n" +"                                       Name:"+obj.getAuthor()+ "\n"+"Type :"+obj.getSubject()+"\n");                 

        }         
Esterify answered 22/6, 2016 at 5:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.