Подтвердить что ты не робот

Передача ArrayList только в качестве значения, а не ссылки

Проще говоря, у меня есть метод с параметром ArrayList. В методе я изменяю содержимое ArrayList для целей, относящихся только к тому, что возвращается методом. Поэтому я не хочу, чтобы ArrayList передавался как параметр, который должен быть затронут вообще (т.е. Не передан как ссылка).

Все, что я пробовал, не удалось добиться желаемого эффекта. Что мне нужно сделать, чтобы я мог использовать копию массива ArrayList только в этом методе, но не изменить его фактическую?

4b9b3361

Ответ 1

Даже если у вас был способ передать список массивов в виде копии, а не по ссылке, это было бы только мелкой копией.

Я бы сделал что-то вроде:

void foo(final ArrayList list) {

    ArrayList listCopy = new ArrayList(list);
    // Rest of the code

}

И просто работайте над скопированным списком.

Ответ 2

Вы можете создать копию ArrayList с помощью конструктора копирования ArrayList:

ArrayList copy = new ArrayList(original);

Но если элементы списка также являются объектами, вы должны знать, что изменение члена копии также изменит этот элемент в оригинале.

Ответ 3

Вы можете передать Collections#unmodifiableList(yourList), чтобы отправить неизменяемую копию своего списка. Кстати, ваш List<Whatever> передается по значению, так как Java всегда проходит по значению, обратите внимание, что в методе foo(List<Whatever> list) вы не можете изменить значение list, но вы можете изменить его содержимое.

public class MyClass {

    List<Whatever> list = new ArrayList<Whatever>();

    public void bar() {
        //filling list...
        foo(Collections.unmodifiableList(list));
    }

    public void foo(List<Whatever> list) {
        //do what you want with list except modifying it...
    }
}

Ответ 4

Вы можете использовать метод .clone или CopyOnWriteArrayList для создания копии, тем самым не влияя на оригинал.

Ответ 5

Попробуйте это в вашем методе:

void method(List<Integer> list) {
        List copyList =  new ArrayList<Integer>();
        copyList.addAll(list); // This will create a copy of all the emlements of your original list
    }

Ответ 6

Просто клонируйте его.

public ArrayList cloneArrayList(ArrayList lst){
    ArrayList list = new ArrayList();
    for (int i=0; i<lst.size(); i++){
        list.add(lst.get(i));
    }
    return list;
}

Добавьте предложение в комментарии, вы также можете использовать

ArrayList copy = new ArrayList(original);

а также

ArrayList copy = new ArrayList();
copy.addAll(original);

Ответ 7

Я не уверен, почему, даже после new ArrayList<MyObj>(old) объект все еще менял ссылку в тех местах, где он не предполагался. Поэтому мне пришлось создать экземпляр новой копии объектов внутри.

Я сделал конструктор копирования, подобный тому, который был на ArrayList, и мне понравилось

 newArray = new ArrayList<MyObj>();
        for (int i = 0; i < oldArray.size(); i++) {
            newArray.add(new MyObj(ondArray.get(i)));
        }

Просто надейтесь помочь кому-то другому, если ответа от Avi недостаточно в вашем случае, как у меня с кодом, слишком грязным, чтобы даже понять = P

Ответ 8

В строках существующих ответов, но используя API ArrayList. Вы можете использовать метод subList(fromIndex, toIndex). Он явно создает представление списка только с нужными элементами (конечно, в последовательности). Здесь, даже если вы измените представление с помощью операций добавления/удаления etc, он не изменит исходный список. Это избавит вас от явного создания копии.

Что-то вроде этого:

public void recursiveMethod(List<Integer> list) {
    if(base)
         return;
    recursiveCall(list);

    // following will just create a tail list but will not actually modify the list
    recursiveCall(list.subList(1, list.size());
}