View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.util.internal;
18  
19  import io.netty.util.Recycler;
20  import io.netty.util.Recycler.Handle;
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.List;
25  import java.util.RandomAccess;
26  
27  /**
28   * A simple list which is reyclable. This implementation does not allow {@code null} elements to be added.
29   */
30  public final class RecyclableArrayList extends ArrayList<Object> {
31  
32      private static final long serialVersionUID = -8605125654176467947L;
33  
34      private static final int DEFAULT_INITIAL_CAPACITY = 8;
35  
36      private static final Recycler<RecyclableArrayList> RECYCLER = new Recycler<RecyclableArrayList>() {
37          @Override
38          protected RecyclableArrayList newObject(Handle<RecyclableArrayList> handle) {
39              return new RecyclableArrayList(handle);
40          }
41      };
42  
43      /**
44       * Create a new empty {@link RecyclableArrayList} instance
45       */
46      public static RecyclableArrayList newInstance() {
47          return newInstance(DEFAULT_INITIAL_CAPACITY);
48      }
49  
50      /**
51       * Create a new empty {@link RecyclableArrayList} instance with the given capacity.
52       */
53      public static RecyclableArrayList newInstance(int minCapacity) {
54          RecyclableArrayList ret = RECYCLER.get();
55          ret.ensureCapacity(minCapacity);
56          return ret;
57      }
58  
59      private final Handle<RecyclableArrayList> handle;
60  
61      private RecyclableArrayList(Handle<RecyclableArrayList> handle) {
62          this(handle, DEFAULT_INITIAL_CAPACITY);
63      }
64  
65      private RecyclableArrayList(Handle<RecyclableArrayList> handle, int initialCapacity) {
66          super(initialCapacity);
67          this.handle = handle;
68      }
69  
70      @Override
71      public boolean addAll(Collection<?> c) {
72          checkNullElements(c);
73          return super.addAll(c);
74      }
75  
76      @Override
77      public boolean addAll(int index, Collection<?> c) {
78          checkNullElements(c);
79          return super.addAll(index, c);
80      }
81  
82      private static void checkNullElements(Collection<?> c) {
83          if (c instanceof RandomAccess && c instanceof List) {
84              // produce less garbage
85              List<?> list = (List<?>) c;
86              int size = list.size();
87              for (int i = 0; i  < size; i++) {
88                  if (list.get(i) == null) {
89                      throw new IllegalArgumentException("c contains null values");
90                  }
91              }
92          } else {
93              for (Object element: c) {
94                  if (element == null) {
95                      throw new IllegalArgumentException("c contains null values");
96                  }
97              }
98          }
99      }
100 
101     @Override
102     public boolean add(Object element) {
103         if (element == null) {
104             throw new NullPointerException("element");
105         }
106         return super.add(element);
107     }
108 
109     @Override
110     public void add(int index, Object element) {
111         if (element == null) {
112             throw new NullPointerException("element");
113         }
114         super.add(index, element);
115     }
116 
117     @Override
118     public Object set(int index, Object element) {
119         if (element == null) {
120             throw new NullPointerException("element");
121         }
122         return super.set(index, element);
123     }
124 
125     /**
126      * Clear and recycle this instance.
127      */
128     public boolean recycle() {
129         clear();
130         return RECYCLER.recycle(this, handle);
131     }
132 }