para que sirve settitle en java
¿Combina múltiples colecciones en una sola colección lógica? (5)
Supongamos que tengo un número constante de colecciones (por ejemplo, 3 ArrayLists) como miembros de una clase. Ahora, quiero exponer todos los elementos a otras clases para que simplemente puedan iterar sobre todos los elementos (idealmente, solo lectura). Estoy usando colecciones de guayaba y me pregunto cómo podría usar iterables / iteradores de guayaba para generar una vista lógica en las colecciones internas sin hacer copias temporales.
Aquí está mi solución para eso:
EDITAR - cambió el código un poco
public static <E> Iterable<E> concat(final Iterable<? extends E> list1, Iterable<? extends E> list2)
{
return new Iterable<E>()
{
public Iterator<E> iterator()
{
return new Iterator<E>()
{
protected Iterator<? extends E> listIterator = list1.iterator();
protected Boolean checkedHasNext;
protected E nextValue;
private boolean startTheSecond;
public void theNext()
{
if (listIterator.hasNext())
{
checkedHasNext = true;
nextValue = listIterator.next();
}
else if (startTheSecond)
checkedHasNext = false;
else
{
startTheSecond = true;
listIterator = list2.iterator();
theNext();
}
}
public boolean hasNext()
{
if (checkedHasNext == null)
theNext();
return checkedHasNext;
}
public E next()
{
if (!hasNext())
throw new NoSuchElementException();
checkedHasNext = null;
return nextValue;
}
public void remove()
{
listIterator.remove();
}
};
}
};
}
Plain Java 8 soluciones usando un Stream
.
Número constante
Suponiendo private Collection<T> c, c2, c3
.
Una solución:
public Stream<T> stream() {
return Stream.concat(Stream.concat(c.stream(), c2.stream()), c3.stream());
}
Otra solución:
public Stream<T> stream() {
return Stream.of(c, c2, c3).flatMap(Collection::stream);
}
Número de variable
Suponiendo private Collection<Collection<T>> cs
:
public Stream<T> stream() {
return cs.stream().flatMap(Collection::stream);
}
Puede crear una nueva List
y addAll()
de sus otras List
. A continuación, devuelve una lista no modificable con Collections.unmodifiableList()
.
Si está utilizando al menos Java 8, vea mi otra respuesta .
Si ya está usando Google Guava, vea la respuesta de Sean Patrick Floyd .
Si está atrapado en Java 7 y no quiere incluir Google Guava, puede escribir su propio (solo lectura) Iterables.concat()
usando no más que Iterable
e Iterator
:
Número constante
public static <E> Iterable<E> concat(final Iterable<? extends E> iterable1,
final Iterable<? extends E> iterable2) {
return new Iterable<E>() {
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
final Iterator<? extends E> iterator1 = iterable1.iterator();
final Iterator<? extends E> iterator2 = iterable2.iterator();
@Override
public boolean hasNext() {
return iterator1.hasNext() || iterator2.hasNext();
}
@Override
public E next() {
return iterator1.hasNext() ? iterator1.next() : iterator2.next();
}
};
}
};
}
Número de variable
@SafeVarargs
public static <E> Iterable<E> concat(final Iterable<? extends E>... iterables) {
return concat(Arrays.asList(iterables));
}
public static <E> Iterable<E> concat(final Iterable<Iterable<? extends E>> iterables) {
return new Iterable<E>() {
final Iterator<Iterable<? extends E>> iterablesIterator = iterables.iterator();
@Override
public Iterator<E> iterator() {
return !iterablesIterator.hasNext() ? Collections.emptyIterator()
: new Iterator<E>() {
Iterator<? extends E> iterableIterator = nextIterator();
@Override
public boolean hasNext() {
return iterableIterator.hasNext();
}
@Override
public E next() {
final E next = iterableIterator.next();
findNext();
return next;
}
Iterator<? extends E> nextIterator() {
return iterablesIterator.next().iterator();
}
Iterator<E> findNext() {
while (!iterableIterator.hasNext()) {
if (!iterablesIterator.hasNext()) {
break;
}
iterableIterator = nextIterator();
}
return this;
}
}.findNext();
}
};
}
Con Guava, puede usar Iterables.concat(Iterable<T> ...)
, crea una vista en vivo de todos los iterables, concatenado en uno (si cambia los iterables, la versión concatenada también cambia). A continuación, ajuste la iteración concatenada con Iterables.unmodifiableIterable(Iterable<T>)
(no había visto antes el requisito de solo lectura).
Desde Iterables.concat( .. )
JavaDocs:
Combina múltiples iterables en un solo iterable. El iterable devuelto tiene un iterador que atraviesa los elementos de cada iterable en las entradas. Los iteradores de entrada no son consultados hasta que sea necesario. El iterador iterable devuelto admite
remove()
cuando el iterador de entrada correspondiente lo admite.
Si bien esto no dice explícitamente que se trata de una vista en vivo, la última oración implica que es (que admite el método Iterator.remove()
solo si el iterador de respaldo lo admite no es posible a menos que se use una vista en vivo)
Código de muestra:
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);
Salida:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9999999]
Editar:
A pedido de Damian, aquí hay un método similar que devuelve una vista de colección en vivo
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() {
}
}