Поскольку задокументировано List#add()
для добавления к концу списка, а List#remove(Object)
задокументировано для возврата сначала соответствующий элемент, с которым он сталкивается, ваш звонок выше удалит самый ранний вставленный экземпляр строки "привет".
Поскольку печатное представление трех объектов в списке одинаково, трудно увидеть разницу в поведении. Однако, если вы посмотрите на адреса экземпляров в отладчике, отметив, какой из них вошел в список первым, вы убедитесь, что это также первый & mdash; и единственный & mdash; удаляемый.
В вашем случае, учитывая, что вы используете строковые литералы, они интернированы компилятором (согласно §3.10.5 JLS ), так что вы увидите три из одного экземпляра присутствуют в вашем списке. Чтобы создать отдельные String
экземпляры, попробуйте изменить три вызова вставки на следующие:
/* not final */ String h = "h";
list.add(h + "i"); // not interned, instance 1
list.add(h + "i"); // not interned, instance 2
list.add(h + "i"); // not interned, instance 3
Сравните то, что вы видите в отладчике, используя эти операторы, с вашей исходной программой. Вы видите разницу?
Обратите внимание, что если String
экземпляр h
выше объявлен как final , то все три объединения будут фактически интернированы, что приведет к тому же 1036 * String
экземпляр добавляется в список три раза. Спасибо @xehpuk за исправление моей первоначальной ошибки в квалификаторе final .