2012-01-19 5 views
7

Удивление есть ли эффективный способ, чтобы добавить элемент в ArrayList в Java в большем положении, чем его текущий размер:Java ArrayList добавить элемент вне текущего размера

Сценарий:

ArrayList<Item> items = new ArrayList<Item>; 
    ... let's say I add three elements 

Теперь я хотел бы добавить элемент в положении 10 (оставляя детали от 3 до 10 обнулить)

items.add(10,newItem); // item.size() == 3 

есть ли эффективный способ изменения размера/заполнение ArrayList с нулями? ..

реализация Java делает размер поля частных :-(..

+0

Вместо этого вы должны использовать HashMap или SortedMap. –

+0

Хорошо, использование карты не является решением для хранилищ памяти, мы знаем, что в конце структура заполнена -> TIntObjectHashMap (trove) возможно – ic3

+0

HashMap не поддерживает порядок. A SortedMap - лучший вариант. –

ответ

6

имхо самое лучшее, что вы можете сделать, это items.addAll(Collections.nCopies(6, null)) и надеюсь, что ArrayList реализует какое-то поведение, чтобы внутренне закрепить это

+0

Это хорошо, но немного страшно с точки зрения производительности – ic3

+0

ну nCopies производит только список-Wrapper для массива, и таким образом ваш ArrayList может использовать System .arraycopy для заполнения нулевого значения в зависимости от того, насколько интеллектуально реализовано. – Hachi

+1

public boolean addAll (сборник c) { \t Object [] a = c.toArray(); int numNew = a.length; \t securityCapacity (size + numNew); // Приращения системы modCount .arraycopy (a, 0, elementData, size, numNew); размер + = numNew; \t return numNew! = 0; } } – ic3

-2

Используйте конструктор ArrayList(int initialCapacity) Таким образом, вы можете установить начальную емкость

+1

InitialCapacity не является размером -> Исключение в потоке «main» java.lang.IndexOutOfBoundsException: Index: 9, Size: 0 – ic3

+0

Попробуйте : public static void main (String [] args) { Список ArrayList = новый ArrayList (10); list.add (9,3); } – ic3

0

Я бы предпочел использовать SortedMap вместо списка здесь. Это позволит индексам не существовать:

SorteMap<Integer, Item> myMap = new TreeMap<Integer, Map>(); 
int i=0; 
myMap.put(i++, first); 
myMap.put(i++, second); 
myMap.put(i++, third); 
myMap.put(10, other); 

Если карта действительно не будет работать, как вы заявили. Затем я предложил создать Decorator вокруг ArrayList. В методе insert добавьте нули, чтобы заполнить пустые места. Я бы предложил использовать Gu ForwardingList, чтобы облегчить создание класса. Таким образом, вам нужно будет реализовать только один метод.

+0

Это не опция для памяти raisons ... – ic3

+0

Что здесь с памятью? @John B - исправьте этот код. –

+0

TreeMap с 1mio Объект большой. – ic3

0

Нет, вы не можете сделать это, Но если вы хотите, чтобы сделать это, а затем добавить пустой объект в оставшиеся индекс, такие как ..

ArrayList<Object> items = new ArrayList<Object>(); 
    items.add(new Object()); 
    items.add(new Object()); 
    items.add(new Object()); 
    items.add(3,new Object()); 
+0

На самом деле мне повезло что-то более элегантное :-) – ic3

2

Как насчет этого?

ArrayList<Item> items = new ArrayList<Item>(); 

items.add(new Item(0)); 
items.add(new Item(1)); 
items.add(new Item(2)); 

items.addAll(Collections.<Item>nCopies(7, null)); 
items.add(10,new Item(10)); 

System.out.println(items); 

печатает

[0, 1, 2, null, null, null, null, null, null, null, 10] 
+0

Используйте '10 - items.size' вместо' 7' как более надежную опцию. –

0

Если память и индекс настолько важно, чтобы использовать обычный массив.

Когда это делается для малого использования System.arraycopy, это делает ArrayList внутренним.

-

Даже если вы используете ArrayList и есть миллион объектов рекомендуется использовать ArrayList (интермедиат initialCapacity) -Constructor, чтобы избежать большого количества копировальных операций

1

Использование TreeMap вместо этого. Вот простой пример, чтобы проверить факт получения сообщений. Выполняйте первый и второй тесты отдельно и используйте jvisualvm для проверки размера кучи. Не забудьте выполнить GC несколько раз.

public class Test { 


      public static void main(String[] args) throws InterruptedException { 
       String s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque metus."; 


       //Test 1 
       ArrayList<String> l = new ArrayList<String>(); 

       for (int i = 0; i < 1000000; i++) { 
        l.add(s + " " + i); 
        l.addAll(Collections.nCopies(i % 10, (String)null)); //Add some nulls 
       } 
       //Heap is > 5MB 

       //Test 2 uncomment and comment test 1 
    //   SortedMap<Integer, String> map = new TreeMap<Integer, String>(); 
    //   for (int i = 0; i < 1000000; i++) { 
    //    map.put(i,s + " " + i); 
    //   } 
       //Heap is < 5MB 

       Thread.sleep(100000); 

      } 
    } 

Похоже TreeMap версия даже меньше потребление памяти, чем ArrayList версии. Проверь себя.

+0

Peter, ArrayList - это массив и немного больше. Как возможно, полный массив принимает больший размер, чем любая другая структура? ... Я думаю, что у вашего примера есть проблема (я уверен) – ic3

+0

Мы говорим о полном массиве. – ic3

+0

Массив (s - строка, n-null): snsnnsnnnsnnnnsnnnnns nnnnnnsnnnnnnnns ... и т. Д. Существует много памяти, зарезервированной для ссылок, но установленной в null. У TreeMap нет этой проблемы. Как вы сказали, это массив. Даже массив из 1mio-нулей по-прежнему стоит памяти. Это все о том, как «плотный» - ваш список. –

0

@ icCube- вы сказали, что этот список должен быть заполнен на 90%. Моя идея для этого решения является:

  • Если вы точно знаете размер цели - использовать простой массив
  • Если вы знаете, целевого размера - использование ArrayList с начальной емкостью, как можно ближе к целевому размеру. Положите nulls на l.addAll(Collections.nCopies(n, (String)null));, как сказали люди.
  • Если вы не знаете размер цели - ваш ArrayList будет многократно изменен. Изменение размера означает копирование всего базового массива (он использует Arrays.copyOf). Вы можете себе представить, что произойдет, если массив скопирован - GC имеет много работы. Затем используйте TreeMap.
Смежные вопросы