java-在多个SortedSet对象上进行迭代
作者:互联网
在Java中,我有几个SortedSet实例.我想遍历所有这些集合中的元素.一个简单的选择是创建一个新的SortedSet,例如TreeSet x,使用x.addAll(y_i)将所有单个集合y_1,…,y_n的内容深复制到其中,然后遍历x.
但是有办法避免深层复制吗?我是否只能创建SortedSet类型的视图,该视图将以某种方式封装所有内部集合的迭代器,但表现为单个集合?
解决方法:
I’d prefer an existing, tested solution, rather than writing my own.
我不知道任何现有的解决方案可以完成此任务,因此我花了一些时间为您编写一个.我确信它还有改进的空间,因此请以它为指导.
正如Sandor在his answer中指出的那样,必须施加或假设一些限制.这样的限制之一是,每个SortedSet必须相对于同一顺序进行排序,否则在没有创建新集合的情况下比较它们的元素就没有意义(代表每个单独集合的并集).
下面是我的代码示例,您将注意到,它比创建一个新集合并将所有元素添加到其中相对要复杂得多.
import java.util.*;
final class MultiSortedSetView<E> implements Iterable<E> {
private final List<SortedSet<E>> sets = new ArrayList<>();
private final Comparator<? super E> comparator;
MultiSortedSetView() {
comparator = null;
}
MultiSortedSetView(final Comparator<? super E> comp) {
comparator = comp;
}
@Override
public Iterator<E> iterator() {
return new MultiSortedSetIterator<E>(sets, comparator);
}
MultiSortedSetView<E> add(final SortedSet<E> set) {
// You may remove this `if` if you already know
// every set uses the same comparator.
if (comparator != set.comparator()) {
throw new IllegalArgumentException("Different Comparator!");
}
sets.add(set);
return this;
}
@Override
public boolean equals(final Object o) {
if (this == o) { return true; }
if (!(o instanceof MultiSortedSetView)) { return false; }
final MultiSortedSetView<?> n = (MultiSortedSetView<?>) o;
return sets.equals(n.sets) &&
(comparator == n.comparator ||
(comparator != null ? comparator.equals(n.comparator) :
n.comparator.equals(comparator)));
}
@Override
public int hashCode() {
int hash = comparator == null ? 0 : comparator.hashCode();
return 37 * hash + sets.hashCode();
}
@Override
public String toString() {
return sets.toString();
}
private final static class MultiSortedSetIterator<E>
implements Iterator<E> {
private final List<Iterator<E>> iterators;
private final PriorityQueue<Element<E>> queue;
private MultiSortedSetIterator(final List<SortedSet<E>> sets,
final Comparator<? super E> comparator) {
final int n = sets.size();
queue = new PriorityQueue<Element<E>>(n,
new ElementComparator<E>(comparator));
iterators = new ArrayList<Iterator<E>>(n);
for (final SortedSet<E> s: sets) {
iterators.add(s.iterator());
}
prepareQueue();
}
@Override
public E next() {
final Element<E> e = queue.poll();
if (e == null) {
throw new NoSuchElementException();
}
if (!insertFromIterator(e.iterator)) {
iterators.remove(e.iterator);
}
return e.element;
}
@Override
public boolean hasNext() {
return !queue.isEmpty();
}
private void prepareQueue() {
final Iterator<Iterator<E>> iterator = iterators.iterator();
while (iterator.hasNext()) {
if (!insertFromIterator(iterator.next())) {
iterator.remove();
}
}
}
private boolean insertFromIterator(final Iterator<E> i) {
while (i.hasNext()) {
final Element<E> e = new Element<>(i.next(), i);
if (!queue.contains(e)) {
queue.add(e);
return true;
}
}
return false;
}
private static final class Element<E> {
final E element;
final Iterator<E> iterator;
Element(final E e, final Iterator<E> i) {
element = e;
iterator = i;
}
@Override
public boolean equals(final Object o) {
if (o == this) { return true; }
if (!(o instanceof Element)) { return false; }
final Element<?> e = (Element<?>) o;
return element.equals(e.element);
}
}
private static final class ElementComparator<E>
implements Comparator<Element<E>> {
final Comparator<? super E> comparator;
ElementComparator(final Comparator<? super E> comp) {
comparator = comp;
}
@Override
@SuppressWarnings("unchecked")
public int compare(final Element<E> e1, final Element<E> e2) {
if (comparator != null) {
return comparator.compare(e1.element, e2.element);
}
return ((Comparable<? super E>) e1.element)
.compareTo(e2.element);
}
}
}
}
该课程的内部原理很容易掌握.该视图保留一个排序集合的列表,这些列表是您要迭代的集合.它还需要将用于比较元素的比较器(使用自然顺序为null).您只能将(不同的)集添加到视图中.
其余的魔术发生在此视图的迭代器中.该迭代器保留将从next()返回的元素的PriorityQueue以及各个集合中的迭代器列表.
该队列在任何时候始终每组最多具有一个元素,并且丢弃重复的元素.迭代器还会丢弃空的和用完的迭代器.简而言之,它保证您将遍历每个元素一次(就像在集合中一样).
这是有关如何使用此类的示例.
SortedSet<Integer> s1 = new TreeSet<>();
SortedSet<Integer> s2 = new TreeSet<>();
SortedSet<Integer> s3 = new TreeSet<>();
SortedSet<Integer> s4 = new TreeSet<>();
// ...
MultiSortedSetView<Integer> v =
new MultiSortedSetView<Integer>()
.add(s1)
.add(s2)
.add(s3)
.add(s4);
for (final Integer i: v) {
System.out.println(i);
}
标签:iterator,set,sortedset,java 来源: https://codeday.me/bug/20191121/2049446.html