如何在Java中实现固定大小的“列表”?

8

由于Java核心库没有这样的集合,那么数组是否是最好的选择,特别是如果不想依赖第三方库?


当您尝试向已满列表中添加项目时,您希望出现什么行为?您可能还应该拥有一个检查是否有空间的方法。 - toto2
2
Arrays.asList 正好做到这一点。 - Louis Wasserman
这个问题不太明确:列表是固定的吗?还是它的大小是固定的? - toto2
8个回答

12

Arrays.asList(T ...) 返回由指定数组支持的固定大小列表

Object[] array = new Object[10];
List<Object> fixedList = Arrays.asList(array);

1
那么,如果我尝试向已经包含10个对象的fixedList添加另一个对象,它会抛出异常还是默默失败? - mre
4
使用add会导致UnsupportedOperationException异常,你只能使用set和get方法,它的基本行为类似于一个数组。 - Aviram Segal

5
你可以使用一个数组,或者一个预先初始化了所需大小的 ArrayList<E>
如果你想要主动防止列表扩展,那么使用数组可能是最简单的方法。

1
但是,如果我向ArrayList实例添加一个对象,导致其超出大小限制,它不会自动扩展吗? - mre
@mre:如果你这样做,它就会发生。你是在说你想积极阻止自己这样做吗? - NPE
@aix,是的,我想积极地防止自己这样做。 - mre
1
@mre:好的。在这种情况下,我个人会坚持使用数组。 - NPE
过度设计,这基本上就是Arrays.asList自己实现的。 - Aviram Segal

4
我会为一个 ArrayList 编写一个包装类,然后在 addaddAll 方法中检查列表的大小是否已达到最大限制。如果已经达到最大限制,你可以选择抛出异常(或者不做任何处理,具体取决于你在代码中想要实现的功能)。以下是一个简短的示例:
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
    }

3

只需自己实现。您可以使用基于代理的方法。定义一个由ArrayList支持的列表。将内部列表设置为私有。还需要实现一个简单的limit字段,它具有默认值,也可以通过构造函数进行设置。

您的列表将实现List,对于每个修改内部列表的方法,适当地增加和减少计数。如果大小超过限制,抛出某种异常。类似这样:

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);
    }
    ...
}

您需要处理泛型,并记得支持一次添加多个元素的情况,使用addAll方法。


那么我们拿一个实现了动态扩展数组大小的 ArrayList,然后改变它的行为,这样我们就不能再这样做了?嗯,是的,not not xx 是一样的,但这有点毫无意义,不是吗? - Voo
我不确定你的观点是什么。你是在说他的自定义列表应该由数组支持吗? - hvgotcodes
你删掉了所有 ArrayList 增加的额外功能,所以我们可以直接使用数组本身——或者如果我们需要 add 和其它函数,那么仅仅通过一个数组来备份也更简单。 - Voo
1
是的,那是一个有效的方法,尽管我不同意我“删除了所有其他功能...”。个人而言,我会使用List而不是数组,因为我不想维护当前索引的指针以及所有这些内容,还有泛型,但如果适合他的目的,OP可以使用数组。 - hvgotcodes

2

你可以从ArrayList类继承,重新实现add方法,以防止添加超过给定数量的元素。或者,更好的方法是像Laf指出的那样使用组合:

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
5
在这种情况下,我不建议使用继承,而应该使用一个包装类。重写 add 方法可能会创建更多问题,因为您将变得依赖于 ArrayList 的实现。Josh Bloch 在他的书《Effective Java》中提到了这一点。 - Laf
@mre:我已经发布了一个例子。 - Tudor

0
使用 Collections.unmodifiableList(List<T> list)。这将返回一个泛型的List<T>对象,如果尝试添加(或删除)元素,则会抛出UnsupportedOperationException

0

我可能会被烧伤,但您也可以使用ArrayBlockingQueue来实现这一点。这样做的好处是可以使用常规Collection方法。


它并不提供所有列表方法的访问,尽管它没有实现任何类型的列表 - 特别是基于索引的访问方法,这对我来说将是使用列表的主要原因。 - Rob Hruska
是的,我更新了我的答案以反映它实际上实现了集合操作,而不是列表。 - Perception

-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");                 

        }         

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接