【问题标题】:Any way to set max size of a collection?有什么方法可以设置集合的最大大小?
【发布时间】:2011-03-04 15:55:37
【问题描述】:

有没有办法在 Java 中设置集合的最大大小?

【问题讨论】:

    标签: java collections


    【解决方案1】:

    你可以这样做:

    List<X> list = Arrays.asList(new X[desiredSize]);
    // where X is any Object type (including arrays and enums,
    // but excluding primitives)
    

    结果列表是可修改的,但不能调整大小(即add(e) 和 remove(e) 不起作用,但 set(index, e) 起作用)。

    参考:


    或者:使用Guava,这是一个静态方法,它用最大尺寸装饰现有列表

    public static <T> List<T> setMaxSize(
        final List<T> input, final int maxSize){
    
        return new ForwardingList<T>(){
    
            @Override
            public boolean addAll(Collection<? extends T> collection){
                return standardAddAll(collection);
            }
    
            @Override
            public boolean addAll(int index, Collection<? extends T> elements){
                return standardAddAll(index, elements);
            }
    
            public boolean add(T e) {
                checkMaxSize();
                return delegate().add(e);
            }
    
            @Override
            public void add(final int index, final T e){
                checkMaxSize();
                delegate().add(index, e);
            }
    
            private void checkMaxSize(){
                if(size() >= maxSize){
                    throw new UnsupportedOperationException("Maximum Size "
                        + maxSize + " reached");
                }
            }
    
            @Override
            protected List<T> delegate(){
                return input;
            }
        };
    }
    

    由于所有标准集合类型都存在 ForwardingXxx 类,因此您也可以为其他集合编写类似的装饰器。

    显然,这仅在您的客户端代码使用修饰的集合时才有效。如果您更改基础集合,您将被搞砸(就像 Collections.unmodifiableXXX 方法一样)

    参考:

    【讨论】:

    • 酷。仅适用于列表?
    • 不错。从未使用过番石榴,但我会研究一下。
    • 这个答案怎么样? stackoverflow.com/a/33403310/6648326
    • @MasterJoe2 乍一看,这似乎是个好主意,是的。阅读Effective Java,第 18 条:“优先组合优于继承”以了解基于继承的方法的缺陷。
    【解决方案2】:

    ArrayBlockingQueue 和 LinkedBlockingQueue 都支持最大大小。 LinkedHashMap 支持在达到最大大小时驱逐最旧或最近最少使用的项目。

    当达到最大尺寸时你希望它做什么?

    【讨论】:

      【解决方案3】:

      不适用于 java.util 集合类,但对于任何特定的集合,您都可以扩展它,并根据自己的目的覆盖 .add() 或 .put()。像这样的东西适用于列表:

      public final boolean add(E e) {
          if (this.size() == MAX_SIZE){
              throw new IllegalStateException("List is already at maximum size of " + MAX_SIZE);
          }
          super.add(e);
      }
      

      JavaDoc 说IllegalStateExeption is correct“如果此时由于插入限制无法添加元素”。

      编辑: 正如 Stas Kurilin 在下面指出的那样,您必须小心覆盖所有可能向集合添加内容的方法,例如 @ 987654327@.

      编辑 2: 正如 Paŭlo Ebermann 在下面指出的那样,不添加元素时的正确响应是抛出异常。

      【讨论】:

      • 不支持投票。这不是完美的解决方案。在其他虚拟机中,addAll 可以在没有add() 的情况下实现。明天,可以(嗯..)添加新的添加方法。
      • 您不应在此处返回false:如果此集合不允许重复并且已包含指定元素,则返回 false。 改为抛出异常。
      • @Stas Kurilin:但是 addAll 不能也被重新覆盖吗?
      • @SyntaxT3rr0r,请澄清你的问题,我没听明白 :( 当然,在这样的解决方案中,像 add/addAll (甚至是类)这样的解决方案应该标记为final。
      【解决方案4】:

      您必须实现自己的集合。此外,您对最大尺寸的概念没有完全定义。例如,您是否希望阻止添加新项目?丢弃最旧的物品?最新项目?最大尺寸是一种属性,而不是一种行为。如果要实现此功能,则需要定义行为部分。

      【讨论】:

      • 为什么要实现自己的收藏? LinkedBlockingQueue 或 ArrayBlockingQueue 有什么问题
      【解决方案5】:

      创建您自己的扩展集合的类非常容易。我只是根据自己的情况这样做,扩展 HashSet:

      import java.util.HashSet;
      
      public class LimitedHashSet<E> extends HashSet<E> {
          private static final long serialVersionUID = -23456691722L;
          private final int limit;
      
          public LimitedHashSet(int limit) {
              this.limit = limit;
          }
      
          @Override
          public boolean add(E object) {
              if (this.size() > limit) return false;
              return super.add(object);
          }
      
      } 
      

      【讨论】:

        【解决方案6】:

        如果您不介意外部库,可以使用 Guava 的EvictingQueue。

        Examplesrigalamilitan:

        Queue<String> evictingQueue= EvictingQueue.create(10);
        String message="This Is Evicting Queue ";
        
        for (int i = 1; i <= 15; i++) {
            evictingQueue.add(message + i);
            System.out.println("EvictingQueue size: " + evictingQueue.size());
        }
        
        System.out.println("Poll Queue Evicting");
        while(!evictingQueue.isEmpty()){
            println(evictingQueue.poll());
        }
        

        打印:

        This Is Evicting Queue 6
        This Is Evicting Queue 7
        This Is Evicting Queue 8
        This Is Evicting Queue 9
        This Is Evicting Queue 10
        This Is Evicting Queue 11
        This Is Evicting Queue 12
        This Is Evicting Queue 13
        This Is Evicting Queue 14
        This Is Evicting Queue 15
        

        【讨论】:

          【解决方案7】:

          标准库中的大多数通用集合没有硬容量 - 只是最小的初始分配。我能想到的唯一例外是LinkedBlockingQueue。其他库有其他有界集合,例如 LRUCache。

          如果对您有用的话,创建自己的包装器应该相当简单。

          【讨论】:

            【解决方案8】:

            您可以设置一些集合的初始容量。我不认为你可以设置最大尺寸。

            您可以将该逻辑构建到您的域类(业务逻辑)中以强制执行最大大小。或者你可以创建一个子类....

            【讨论】:

              【解决方案9】:

              如果您的意思是“Collection 接口(或其标准实现)上是否有可以设置大小的方法,答案是否定的。您是否可以编写(或扩展)一个类以使其具有比您确定的最大大小可以。

              【讨论】:

                【解决方案10】:

                也许我有一个类似的案例,因为我想“调整”一个对象集合的大小,我通过两个步骤检索到:

                • 第一步通过 sql 查询检索到 N 个确定项的集合(ROWNUM 完成了这项工作)。

                • 第二步验证结果集合以最终获得另一个大小未确定的集合(可能是

                因此,为了再次从这个“CollectionOfValidatedObjects”中获得恰好 N 个确定的对象的集合,我执行了以下操作:

                public Collection<Object> determineSomeElements(int maxSize){    
                
                
                     Collection<Object> returnValues = new ArrayList<Object>();
                
                      // the initial collection with all retrieved validated elements
                     Collection<Object> myValidatedCollection = getValidatedCollection();
                
                     Iterator<Object> it = myValidatedCollection.iterator();
                
                     
                     // iterate and add a condition with the passed size
                     while(it.hasNext() && returnValues.size() < maxSize) {
                
                           returnValues.add(it.next); }    
                
                     }
                

                }

                【讨论】:

                • 它修剪现有的Collection。 OP 要求限制最大尺寸。
                【解决方案11】:

                这是我自己的最大大小的 ArrayList 代码,根据 Matthew Gilliard 的回答构建。它覆盖了 ArrayList 中的所有三个构造函数,还覆盖了.AddAll()。

                import java.util.ArrayList;
                import java.util.Collection;
                
                public class MaxedArrayList<E> extends ArrayList<E> {
                    final int MAXSIZE;
                
                    public MaxedArrayList(int initialCapacity, final int MAXSIZE) {
                        super(initialCapacity);
                        this.MAXSIZE = MAXSIZE;
                    }
                
                    public MaxedArrayList(final int MAXSIZE) {
                        super();
                        this.MAXSIZE = MAXSIZE;
                    }
                
                    public MaxedArrayList(Collection<? extends E> c, final int MAXSIZE) {
                        super(c);
                        this.MAXSIZE = MAXSIZE;
                        sizeCheck();
                    }
                
                    private boolean sizeCheck() {
                        //returns true if operation is legal.
                        return (size() <= MAXSIZE);
                    }
                
                    private boolean sizeCheck(int deltaElements) {
                        if (deltaElements < 0) throw new IllegalArgumentException();
                        //returns true if operation is legal.
                        return (size() + deltaElements <= MAXSIZE);
                    }
                
                    @Override
                    public void add(int index, E element) throws IllegalStateException {
                        if (!sizeCheck()) throw throwException();
                        super.add(index, element);
                    }
                
                    @Override
                    public boolean addAll(Collection<? extends E> c) throws IllegalStateException {
                        if (!sizeCheck(c.size())) throw throwException();
                        return (super.addAll(c));
                    }
                
                    private IllegalStateException throwException() {
                        return new IllegalStateException("Request is over MaxArrayList max size. Elements not added.");
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 2017-05-17
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-03-09
                  • 2015-03-22
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多