Мой вариант решения задачи не проходит, потому что при изменении копии массива оригинал массива тоже меняется таким же способом! Это вне логики, почему Java тут так работает? Понятно, что я могу все поправить, чтобы работало, но интересно, почему так?
public static Map<String, Integer> countWords(ArrayList<String> list) {
HashMap<String, Integer> result = new HashMap<String, Integer>();
//напишите тут ваш код
ArrayList<String> copy=list;
for (int i = 0; i < 20; i++) {
int count=0;
for (int k = 0; k < 20; k++) if (list.get(i).equals(copy.get(k))) {
count++;
copy.set(k,"");}
if (count>0) result.put(list.get(i),count);
}
return result;
}
Николай
41 уровень
Что за треш, почему Java так работает?
Решен
Комментарии (9)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Justinian Judge в Mega City One Master
13 августа 2019, 17:33решение
Объекты в джава создаются при помощи двух способов, оператора new или метода Class.newInstance().
Если их нет явно при инициализации переменной, или нету если пройти вглубь (например Set<String> set = getNewSet(); в самом методе будет создаваться сет и возвращаться) - значит объекта не будет создаваться.
Нет создания объекта - нет копии. Ведь копия, это когда был один объект в памяти, а стало два объекта в памяти.
ArrayList<String> copy = list;
ArrayList<String> - тип переменной
copy - название переменной;
list - ссылка на конкретный объект в памяти.
Результат работы этой строки - мы объявляем переменную ссылочного типа, и инициализируем ее значением - а именно, ссылкой на конкретный объект.
Итого: объект как был один так и остался. Просто добавилась ссылка на него.
Теперь в рамках метода, ты можешь одинаково с ним работать как через copy , так и через лист.
Грубо говоря - ты сделал дубликат ключей от дома, и утверждаешь, что по такой логике - должна создаться новая копия дома.
Нет, дом один, просто ключей стало больше. Или телевизор один - пультов много, по терминологии Head first Java.
Переменные ссылочного типа хранят ссылки на объекты.
Ссылка на объект != объект.
Со стрингом очень неудачный пример, поскольку там синтаксически и конструктор по другому обрабатывается, и пул стрингов, и тд.
+2
Николай
14 августа 2019, 09:59
Спасибо, вот теперь все понятно. Переделал строку на
ArrayList<String> copy=new ArrayList<String>(list);
и все заработало, как надо. Получается, нужно просто запомнить, что String - исключение, надеюсь, единственное, когда новый объект создается без всякого new и Class.newInstance().
0
Justinian Judge в Mega City One Master
14 августа 2019, 11:05полезный
Если есть новый объект, значит есть и слово new. Другой вопрос, что оно может быть в другом месте. В случае со стрингом, синтаксически сделали так что строка:
String s = "something"; фактически создает новый объект, просто для удобства в этом случае позволено не указывать явный конструктор, ибо:
То есть в строке
String s = new String("Michael");
фактически создается даже два объекта. Сначала инстанциируется стринговый литерал "Michael", а потом явным образом создается еще объект, который и получает ссылку на стрингу в стринг пуле.
Ну или как вариант, int[] array = {1, 2, 3, 4};
ключевого слова new нету, значит ли что объект создается просто так? Нет, массив , как и стринга достаточно базовая штука в архитектуре, но если массив это объект, где можно увидеть класс Array , на базе которого создаются массивы, где можно увидеть поле length?
Увидеть могут лишь не все, вернее мало кто это может.
Функционирование фишечек обеспечивается синтаксисом, но снова-таки - под капотом все по взрослому. Поэтому общего правила это не отменяет, я бы даже не назвал это исключениями, это особенности работы.
Как например при работе конструктора дочернего класса, компилятор вставит сам конструктор родительского если мы не укажем явно. +1
IceBergMaster
13 августа 2019, 13:58
Какая же это копия? Это один список и две переменные.
Поздновато у вас этот вопрос возник) На 26 уровне уже должно быть понимание разницы между объектом и переменной/ссылкой.
0
Николай
13 августа 2019, 14:12
Хм. Я изменяю copy, а изменяется заодно и list?! Почему тут не как со String?
String st="оригинал";
String st2=st;
st2="копия";
st2 ссылается на тот же объект, что и st. Но когда st2 задается новое значение, то появляется новый объект и st2 ссылается на него же. При этом в st не появляется значение "копия" - нет такого, что меняется оригинальный объект.
0
IceBergMaster
13 августа 2019, 14:16
st2 сначала ссылалась на один объект, потом стала ссылаться на другой, а st какое имеет отношение ко второму объекту?
0
Николай
13 августа 2019, 14:27
Никакого. Но в моем примере делается то же самое, а результат другой.
ArrayList<String> copy=list;
copy.set(k,"");
В итоге list на позиции k тоже изменяется. То есть нет аналогии со String почему то. Хотя логично было бы по аналогии со String - создание нового массива, copy ссылается на новый массив, а list - на тот же первый массив.
0
IceBergMaster
13 августа 2019, 14:31
Так аналогия совсем неуместна
"создание нового массива, copy ссылается на новый массив" - так нигде не создается новый массив, точнее список, есть один список и две переменные ссылаются на него.
В случае со строками у тебя есть два объекта "оригинал" и "копия", и две переменные которые ссылаются на эти два объекта соответственно.
0
Wladyslaw Java Developer Master
13 августа 2019, 16:35
это равносильно
Не совсем, на самом деле, но я думаю это поможет тебе понять суть ссылки
0