Основное отличие состоит в том, что C # (если говорить о сети) выполняется на сервере и JS на клиенте . Вы не можете выполнить C # на клиенте. Вот и все. Оба языка завершены по Тьюрингу, так что не волнуйтесь:)
Обычно, когда вы удаляете элемент из коллекции во время цикла по коллекции, вы получить исключение одновременной модификации . Отчасти поэтому интерфейс Iterator имеет метод remove (). Использование итератора - единственный безопасный способ изменить коллекцию элементов при их обходе.
Код будет выглядеть примерно так:
Set<SomeClass> set = new HashSet<SomeClass>();
fillSet(set);
Iterator<SomeClass> setIterator = set.iterator();
while (setIterator.hasNext()) {
SomeClass currentElement = setIterator.next();
if (setOfElementsToRemove(currentElement).size() > 0) {
setIterator.remove();
}
}
Таким образом вы безопасно удалите все элементы, которые генерируют набор для удаления из вашего setOfElementsToRemove ( ).
РЕДАКТИРОВАТЬ
На основании комментария к другому ответу, это может быть больше того, что вам нужно:
Set<SomeClass> set = new HashSet<SomeClass>();
Set<SomeClass> removalSet = new HashSet<SomeClass>();
fillSet(set);
for (SomeClass currentElement : set) {
removalSet.addAll(setOfElementsToRemove(currentElement);
}
set.removeAll(removalSet);
Вместо того, чтобы перебирать все элементы в наборе, чтобы удалить те, которые вам нужны, вы можете использовать Коллекции Google (хотя вы не можете сделать это самостоятельно) и применить Предикат для маски тех, которые вам не нужны.
package com.stackoverflow.q1675037;
import java.util.HashSet;
import java.util.Set;
import org.junit.Assert;
import org.junit.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
public class SetTest
{
public void testFilter(final Set<String> original, final Set<String> toRemove, final Set<String> expected)
{
Iterable<String> mask = Iterables.filter(original, new Predicate<String>()
{
@Override
public boolean apply(String next) {
return !toRemove.contains(next);
}
});
HashSet<String> filtered = Sets.newHashSet(mask);
Assert.assertEquals(original.size() - toRemove.size(), filtered.size());
Assert.assertEquals(expected, filtered);
}
@Test
public void testFilterNone()
{
Set<String> original = new HashSet<String>(){
{
this.add("foo");
this.add("bar");
this.add("foobar");
}
};
Set<String> toRemove = new HashSet();
Set<String> expected = new HashSet<String>(){
{
this.add("foo");
this.add("bar");
this.add("foobar");
}
};
this.testFilter(original, toRemove, expected);
}
@Test
public void testFilterAll()
{
Set<String> original = new HashSet<String>(){
{
this.add("foo");
this.add("bar");
this.add("foobar");
}
};
Set<String> toRemove = new HashSet<String>(){
{
this.add("foo");
this.add("bar");
this.add("foobar");
}
};
HashSet<String> expected = new HashSet<String>();
this.testFilter(original, toRemove, expected);
}
@Test
public void testFilterOne()
{
Set<String> original = new HashSet<String>(){
{
this.add("foo");
this.add("bar");
this.add("foobar");
}
};
Set<String> toRemove = new HashSet<String>(){
{
this.add("foo");
}
};
Set<String> expected = new HashSet<String>(){
{
this.add("bar");
this.add("foobar");
}
};
this.testFilter(original, toRemove, expected);
}
@Test
public void testFilterSome()
{
Set<String> original = new HashSet<String>(){
{
this.add("foo");
this.add("bar");
this.add("foobar");
}
};
Set<String> toRemove = new HashSet<String>(){
{
this.add("bar");
this.add("foobar");
}
};
Set<String> expected = new HashSet<String>(){
{
this.add("foo");
}
};
this.testFilter(original, toRemove, expected);
}
}
Любое решение, которое включает удаление из набора, который вы повторяете, во время итерации, но не через итератор, абсолютно не будет работать. Кроме, возможно, одного: вы можете использовать Collections.newSetFromMap (new ConcurrentHashMap
. Загвоздка в том, что теперь ваш итератор только слабо согласован , что означает, что каждый раз, когда вы удаляете элемент, с которым еще не сталкивались, не определено, появится ли этот элемент позже в вашей итерации или нет. Если это не проблема, это может сработать для вас.
Еще вы можете создать набор toRemove
по ходу работы, а затем set.removeAll (itemsToRemove);
] только в конце. Или скопируйте набор перед тем, как начать,
Вы можете попробовать java.util.concurrent.CopyOnWriteArraySet
, который дает вам итератор, который представляет собой снимок набора во время создания итератора. Любые изменения, которые вы вносите в набор (например, вызывая removeAll ()
), не будут видны в итераторе, но будут видны, если вы посмотрите на сам набор (и removeAll ()
] не бросит).
На этот вопрос есть простой ответ - используйте метод Iterator.remove ().
If you have enough memory for one copy of the set, I'll assume you also have enough memory for two copies. The Kafka-esque rules you cite don't seem to forbid that :)
My suggestion, then:
fillSet(set);
fillSet(copy);
for (Object item : copy) {
if (set.contains(item)) { // ignore if not
set.removeAll(setOfStuffToRemove())
}
}
so copy stays intact and just provides the stuff to loop on, while set suffers deletions. Stuff that was removed from set in the meantime will be ignored.
Почему бы вам не использовать метод удаления итератора для объектов, которые вы хотите удалить ?
Итераторы были введены в основном потому, что счетчики не могли обрабатывать удаление во время перечисления.
Вы должны вызвать метод Iterator.remove
.
Также обратите внимание, что в большинстве коллекций java.util
remove
] вызовет исключение, если содержимое коллекции изменилось. Поэтому, если код является многопоточным, будьте осторожны или используйте параллельные коллекции.
Можно реализовать Набор
, который позволяет удалять его элементы во время итерации по нему.
Я думаю, что стандартные реализации (HashSet, TreeSet и т. Д.) запретить это, потому что это означает, что они могут использовать более эффективные алгоритмы, но это несложно.
Вот неполный пример с использованием Google Collections:
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.base.Predicates;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
public class ConcurrentlyModifiableSet<E>
extends ForwardingSet<E> {
/** Create a new, empty set */
public ConcurrentlyModifiableSet() {
Map<E, Boolean> map = new ConcurrentHashMap<E, Boolean>();
delegate = Sets.newSetFromMap(map);
}
@Override
public Iterator<E> iterator() {
return Iterators.filter(delegate.iterator(), Predicates.in(delegate));
}
@Override
protected Set<E> delegate() {
return this.delegate;
}
private Set<E> delegate;
}
Примечание: итератор не поддерживает remove ()
операция (но пример в вопросе не требует этого.)