ArrayList не клонируется

370
12 февраля 2017, 10:37

Здравствуйте,

Пытаюсь клонировать ArrayList со всеми переменными. В итоге изменяю значения градусов в новом листе. И автоматически изменяются данные в старом листе. Хотя использую пример, в котором данные старого листа должны остаться неизменными.

ArrayList<HeatSensor> celsius = new ArrayList<HeatSensor>();
ArrayList<HeatSensor> fareng = (ArrayList<HeatSensor>) celsius.clone();
for(HeatSensor h: fareng) { 
    double far = h.getCelsius();
    far = 9*far/5 + 32;
    h.setCelsius(far);
    System.out.println(h.toString());
}

Чтобы было понятнее, вот что выводится на экран:

================celsius============================  
Heat : 70.0, 1/02/2017  
Heat : 30.0, 1/02/2017  
Heat : 35.0, 3/02/2017  
================fahrenheit==========================  
Heat : 158.0, 1/02/2017  
Heat : 86.0, 1/02/2017  
Heat : 95.0, 3/02/2017  
================celsius============================    
Heat : 158.0, 1/02/2017   
Heat : 86.0, 1/02/2017    
Heat : 95.0, 3/02/2017    

Так же имеется другой вопрос относительно этой же программы. найти максимальное значение в ArrayList

Answer 1

Метод clone определен в ArrayList как копирование ссылок элементов.

public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

Таким образом, элементы равны с точностью до ссылки celsius.get(i) == fareng.get(i) для любого i, и при изменении элемента в одном списке вы измените его же в другом списке.

Для решения вашего вопроса нужно воспользоваться глубоким копированием, то есть сделать дополнительно и копии самих элементов.

for (HeatSensor h : celsius) {
    fareng.add(h.clone());
}

P.S. в разработке не рекомендуется использовать метод clone. Он считается плохим дизайном в приложении. Вам стоит воспользоваться копированием через конструктор.

List<HeatSensor> fareng = new ArrayList<>(celsius.size());
for (HeatSensor h : celsius) {
     fareng.add(new HeatSensor(h));
} 

И сам конструктор:

public HeatSensor(HeatSensor another) {
     this.celsius = another.celsius; // и так далее по аналогии
}
Answer 2

Реализуйте метод clone() в классе HeatSensor и клонируйте списки следующим образом:

ArrayList<HeatSensor> celsius = new ArrayList<>();
ArrayList<HeatSensor> fareng = new ArrayList<>();
for (HeatSensor h : celsius)
        fareng.add(h.clone());

Ваш вариант не работает, т.к. клонируются списки, но объекты остаются одни и те же.

READ ALSO
найти максимальное значение в ArrayList

найти максимальное значение в ArrayList

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

530
Navigation Drawer в фрагменте [дубликат]

Navigation Drawer в фрагменте [дубликат]

На данный вопрос уже ответили:

266