Почему итератор определяет операцию remove ()?
в C#IEnumerator интерфейс определяет способ прохождения коллекции и просмотра элементов. Я думаю, что это чрезвычайно полезно, потому что если вы передадите IEnumerable<T>
для метода он не будет изменять исходный источник.
однако, на Java,итератор определяет удалить операции (при необходимости!) разрешить удаление элементов. Нет никакого преимущества в прохождении Iterable<T>
к методу, потому что этот метод все еще может изменить оригинальная коллекция.
remove
' s optionalness пример отказано в завещании запах, но игнорируя это (уже обсуждалось здесь) я был бы заинтересован в дизайнерских решениях, которые вызвали remove
мероприятие будет реализовано в интерфейсе.
каковы проектные решения, которые привели к remove
добавляется Iterator
?
другими словами, каково дизайнерское решение C#, которое явно нет remove
определен IEnumerator
?
4 ответов
Iterator
способен удалять элементы во время итерации. Нельзя выполнить итерацию коллекции с помощью итератора и удалить элементы из целевой коллекции с помощью remove()
метод этой коллекции. Вы получите ConcurrentModificationException
при следующем вызове Iterator.next()
потому что итератор не может знать, как именно была изменена коллекция, и не может знать, как продолжить итерацию.
при использовании remove()
итератора, он знает, как коллекция была изменена. Более того, на самом деле вы не можете удалить элемент коллекции, но только текущий. Это упрощает продолжение итерации.
Что касается преимуществ прохождения итератора или Iterable: вы всегда можете использовать Collection.unmodifireableSet()
или Collection.unmodifireableList()
для предотвращения изменения вашей коллекции.
вероятно, это связано с тем, что удаление элементов из коллекции во время итерации по ней всегда было причиной ошибок и странного поведения. Из чтения документации можно предположить, что Java enforces во время выполнения remove() вызывается только один раз за вызов next (), что заставляет меня думать, что он только что был добавлен, чтобы предотвратить беспорядочное удаление данных из списка при итерации по нему.
есть ситуации, когда вы хотите иметь возможность удалять элементы с помощью итератора, потому что это самый эффективный способ сделать это. Например, при обходе связанной структуры данных (например, связанного списка) удаление с помощью итератора является O(1)
операции ... по сравнению с O(N)
через List.remove()
операции.
и конечно много коллекции разработаны таким образом, что изменение коллекции во время коллекции любым другим способом, чем Iterator.remove()
будет в результате ConcurrentModificationException
.
если у вас есть ситуация, когда вы не хотите разрешать модификацию через итератор коллекции, оберните его с помощью Collection.unmodifiableXxxx
и использование итератора будет иметь желаемый эффект. Кроме того, я думаю, что Apache Commons предоставляет простую немодифицируемую оболочку итератора.
кстати IEnumerable
страдает от того же" запаха", что и Iterator
. Взгляните на reset()
метод. Мне также было любопытно, как C# LinkedList
класс O(N)
удалить проблему. Похоже, что это разоблачение внутренних частей списка ... в форме First
и Last
свойства, значения которых являются LinkedListNode
ссылки. Это нарушает другой принцип проектирования ... и (Имо) намного опаснее, чем Iterator.remove()
.
это на самом деле удивительная особенность Java. Как вы знаете, при итерации по списку в .NET для удаления элементов (для которых существует несколько вариантов использования) у вас есть только два варианта.
var listToRemove = new List<T>(originalList);
foreach (var item in originalList)
{
...
if (...)
{
listToRemove.Add(item)
}
...
}
foreach (var item in listToRemove)
{
originalList.Remove(item);
}
или
var iterationList = new List<T>(originalList);
for (int i = 0; i < iterationList.Count; i++)
{
...
if (...)
{
originalList.RemoveAt(i);
}
...
}
теперь я предпочитаю второй, но с Java мне не нужно все это, потому что, пока я нахожусь на элементе, я могу удалить его, и все же итерация будет продолжаться! Честно говоря, хотя это может показаться неуместным, это действительно оптимизация во многом.