은 여기 Iterator<Iterator<T>>
을하고 Iterator<T>
로 바뀝니다 중첩 된 반복자입니다. 또한 Iterator<V>
개체를 Map<K,V>
밖으로 성장시킬 수있는 정적 메서드가 있으며 일부 고차원 도구 (Iterator<Iterator<V>>
및 Map<K,Map<K,V>
등)가 함께 제공됩니다.
Iterator<Iterator<Iterator<T>>>
과 같이 더 높은 수준의 반복기를 반복하는 아이디어는 3 방향 테스트 및 MapMapMap 테스트에서 볼 수있는 것처럼 다른 쪽을 다른 안에 래핑하는 것입니다.
public class NestedIterator<T> implements Iterator<T> {
// Outer iterator. Goes null when exhausted.
Iterator<Iterator<T>> i2 = null;
// Inner iterator. Goes null when exhausted.
Iterator<T> i1 = null;
// Next value.
T next = null;
// Takes a depth-2 iterator.
public NestedIterator(Iterator<Iterator<T>> i2) {
this.i2 = i2;
// Prime the pump.
if (i2 != null && i2.hasNext()) {
i1 = i2.next();
}
}
@Override
public boolean hasNext() {
// Is there one waiting?
if (next == null) {
// No!
// i1 will go null if it is exhausted.
if (i1 == null) {
// i1 is exhausted! Get a new one from i2.
if (i2 != null && i2.hasNext()) {
/// Get next.
i1 = i2.next();
// Set i2 null if exhausted.
if (!i2.hasNext()) {
// Exhausted.
i2 = null;
}
} else {
// Exhausted.
i2 = null;
}
}
// A null i1 now will mean all is over!
if (i1 != null) {
if (i1.hasNext()) {
// get next.
next = i1.next();
// Set i1 null if exhausted.
if (!i1.hasNext()) {
// Exhausted.
i1 = null;
}
} else {
// Exhausted.
i1 = null;
}
}
}
return next != null;
}
@Override
public T next() {
T n = next;
next = null;
return n;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
// Iterating across Maps of Maps of Maps.
static <K1, K2, K3, V> Iterator<Iterator<Iterator<V>>> iiiV(Map<K1, Map<K2, Map<K3, V>>> i) {
final Iterator<Map<K2, Map<K3, V>>> iV = iV(i);
return new Iterator<Iterator<Iterator<V>>>() {
@Override
public boolean hasNext() {
return iV.hasNext();
}
@Override
public Iterator<Iterator<V>> next() {
return iiV(iV.next());
}
@Override
public void remove() {
iV.remove();
}
};
}
// Iterating across Maps of Maps.
static <K1, K2, V> Iterator<Iterator<V>> iiV(Map<K1, Map<K2, V>> i) {
final Iterator<Map<K2, V>> iV = iV(i);
return new Iterator<Iterator<V>>() {
@Override
public boolean hasNext() {
return iV.hasNext();
}
@Override
public Iterator<V> next() {
return iV(iV.next());
}
@Override
public void remove() {
iV.remove();
}
};
}
// Iterating across Map values.
static <K, V> Iterator<V> iV(final Map<K, V> map) {
return iV(map.entrySet().iterator());
}
// Iterating across Map.Entry Iterators.
static <K, V> Iterator<V> iV(final Iterator<Map.Entry<K, V>> i) {
return new Iterator<V>() {
@Override
public boolean hasNext() {
return i.hasNext();
}
@Override
public V next() {
return i.next().getValue();
}
@Override
public void remove() {
i.remove();
}
};
}
// **** TESTING ****
enum I {
I1, I2, I3;
};
public static void main(String[] args) {
// Two way test.
testTwoWay();
System.out.flush();
System.err.flush();
// Three way test.
testThreeWay();
System.out.flush();
System.err.flush();
// MapMap test
testMapMap();
System.out.flush();
System.err.flush();
// MapMapMap test
testMapMapMap();
System.out.flush();
System.err.flush();
}
private static void testMapMap() {
Map<String,String> m = new TreeMap<>();
m.put("M-1", "V-1");
m.put("M-2", "V-2");
Map<String,Map<String,String>> mm = new TreeMap<>();
mm.put("MM-1", m);
mm.put("MM-2", m);
System.out.println("MapMap");
Iterator<Iterator<String>> iiV = iiV(mm);
for (Iterator<String> i = new NestedIterator<>(iiV); i.hasNext();) {
System.out.print(i.next() + ",");
}
System.out.println();
}
private static void testMapMapMap() {
Map<String,String> m = new TreeMap<>();
m.put("M-1", "V-1");
m.put("M-2", "V-2");
m.put("M-3", "V-3");
Map<String,Map<String,String>> mm = new TreeMap<>();
mm.put("MM-1", m);
mm.put("MM-2", m);
Map<String,Map<String,Map<String,String>>> mmm = new TreeMap<>();
mmm.put("MMM-1", mm);
mmm.put("MMM-2", mm);
System.out.println("MapMapMap");
Iterator<Iterator<Iterator<String>>> iiiV = iiiV(mmm);
for (Iterator<String> i = new NestedIterator<>(new NestedIterator<>(iiiV)); i.hasNext();) {
System.out.print(i.next() + ",");
}
System.out.println();
}
private static void testThreeWay() {
// Three way test.
System.out.println("Three way");
List<Iterator<I>> lii1 = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
List<Iterator<I>> lii2 = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
List<Iterator<I>> lii3 = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
Iterator<Iterator<Iterator<I>>> liii = Arrays.asList(
lii1.iterator(),
lii2.iterator(),
lii3.iterator()).iterator();
// Grow a 3-nest.
// Unroll it.
for (Iterator<I> ii = new NestedIterator<>(new NestedIterator<>(liii)); ii.hasNext();) {
I it = ii.next();
System.out.print(it + ",");
}
System.out.println();
}
private static void testTwoWay() {
System.out.println("Two way");
List<Iterator<I>> lii = Arrays.asList(
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator(),
EnumSet.allOf(I.class).iterator());
for (Iterator<I> ii = new NestedIterator<>(lii.iterator()); ii.hasNext();) {
I it = ii.next();
System.out.print(it + ",");
}
System.out.println();
}
}
코드는 이제 이와 비슷한 형태가 될 수 있습니다. 필자는 이것을 전혀 테스트하지 않았으므로 가능한 경우 ConcurrentSkipListMap
대신 Map
을 사용하고 Java 7에서 <>
을 많이 사용하고 있습니다.
public class MyCustomIndex implements Iterable<byte[]> {
private Map<byte[], Map<byte[], Map<byte[], byte[]>>> table;
public MyCustomIndex() {
this.table = new ConcurrentSkipListMap<>();
}
/**
* @param K
* @param F
* @param Q
*/
public void put(byte[] K, byte[] F, byte[] Q) {
Map<byte[], byte[]> QToDummyValueMap;
Map<byte[], Map<byte[], byte[]>> FToQMap;
if (table.containsKey(K)) {
FToQMap = table.get(K);
if (FToQMap.containsKey(F)) {
QToDummyValueMap = FToQMap.get(F);
} else {
QToDummyValueMap = new ConcurrentSkipListMap<>();
}
} else {
QToDummyValueMap = new ConcurrentSkipListMap<>();
FToQMap = new ConcurrentSkipListMap<>();
}
QToDummyValueMap.put(Q, new byte[0]);
FToQMap.put(F, QToDummyValueMap);
table.put(K, FToQMap);
}
public Map<byte[], Map<byte[], Map<byte[], byte[]>>> gettable() {
return table;
}
public Iterator<byte[]> iterator() {
// **** This is what I have been aiming at all along ****
return new NestedIterator(new NestedIterator<>(NestedIterator.iiiV(table)));
}
}