За допомогою програми Guava ви можете використовувати Iterables.concat(Iterable<T> ...)
, вона створює перегляд у реальному часі всіх ітерабелів, об'єднаних в один (якщо ви змінюєте ітерабелі, також змінюється і конкатенована версія). Потім оберніть з'єднаний ітерабельний Iterables.unmodifiableIterable(Iterable<T>)
(я раніше не бачив вимоги лише для читання).
З Iterables.concat( .. )
JavaDocs:
Поєднує кілька ітерабелів в один ітерабельний. Повертається ітерабельний файл має ітератор, який переміщує елементи кожного ітерабельного введення. Ітератори введення не опитуються до необхідності. Ітератор, що повертається, підтримує ітератор, remove()
коли його підтримує відповідний ітератор введення.
Хоча це прямо не говорить про те, що це перегляд у прямому ефірі, з останнього речення випливає, що воно є (підтримка Iterator.remove()
методу лише в тому випадку, якщо підтримуючий ітератор підтримує його неможливо, якщо не використовувати прямий перегляд)
Приклад коду:
final List<Integer> first = Lists.newArrayList(1, 2, 3);
final List<Integer> second = Lists.newArrayList(4, 5, 6);
final List<Integer> third = Lists.newArrayList(7, 8, 9);
final Iterable<Integer> all =
Iterables.unmodifiableIterable(
Iterables.concat(first, second, third));
System.out.println(all);
third.add(9999999);
System.out.println(all);
Вихід:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9999999]
Редагувати:
За запитом від Damian, ось подібний метод, який повертає прямий перегляд колекції
public final class CollectionsX {
static class JoinedCollectionView<E> implements Collection<E> {
private final Collection<? extends E>[] items;
public JoinedCollectionView(final Collection<? extends E>[] items) {
this.items = items;
}
@Override
public boolean addAll(final Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
for (final Collection<? extends E> coll : items) {
coll.clear();
}
}
@Override
public boolean contains(final Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean isEmpty() {
return !iterator().hasNext();
}
@Override
public Iterator<E> iterator() {
return Iterables.concat(items).iterator();
}
@Override
public boolean remove(final Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(final Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public int size() {
int ct = 0;
for (final Collection<? extends E> coll : items) {
ct += coll.size();
}
return ct;
}
@Override
public Object[] toArray() {
throw new UnsupportedOperationException();
}
@Override
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
@Override
public boolean add(E e) {
throw new UnsupportedOperationException();
}
}
/**
* Returns a live aggregated collection view of the collections passed in.
* <p>
* All methods except {@link Collection#size()}, {@link Collection#clear()},
* {@link Collection#isEmpty()} and {@link Iterable#iterator()}
* throw {@link UnsupportedOperationException} in the returned Collection.
* <p>
* None of the above methods is thread safe (nor would there be an easy way
* of making them).
*/
public static <T> Collection<T> combine(
final Collection<? extends T>... items) {
return new JoinedCollectionView<T>(items);
}
private CollectionsX() {
}
}