1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class LinkedHashsetIteratorSaver {
private static Class<?> IC = getIteratorClass("java.util.LinkedHashMap$LinkedKeyIterator");
private static Class<?> MIC = getIteratorClass("java.util.LinkedHashMap$LinkedHashIterator");
private static Class<?> getIteratorClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
/**
* Crée une copie de l'itérateur qui permet de recommencer l'itération même si on continue d'itérer sur celui passé en argumnt
* @param iterator itérateur à copier
* @param restartFromCurrent si true, on réintère à partir de la dernière valeur obtenur, sinon à partir de la prochaine et l'état est inchangé
* @return
*/
public static <T> Iterator<T> saveIterator(Iterator<T> iterator, boolean restartFromCurrent) {
if ( !IC.isAssignableFrom(iterator.getClass()) ) {
throw new IllegalArgumentException("Must be a LinkedHashSet iterator");
}
try {
Object next = read("next",iterator);
Object current = read("current",iterator);
Object expectedModCount = read("expectedModCount",iterator);
Object owner = read("this$0",iterator);
Constructor<? extends Iterator> constr = iterator.getClass().getDeclaredConstructor(LinkedHashMap.class);
constr.setAccessible(true);
Object newiterator = constr.newInstance(owner);
if ( restartFromCurrent && current!=null ) {
set(newiterator, "next", current);
}
else {
set(newiterator, "next", next);
}
set(newiterator, "expectedModCount", expectedModCount);
return (Iterator<T>) newiterator;
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
catch (InvocationTargetException | NoSuchMethodException e) {
throw new IllegalStateException(e);
}
catch (InstantiationException e) {
throw new IllegalStateException(e);
}
}
private static void set(Object object, String name, Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field f = MIC.getDeclaredField(name);
f.setAccessible(true);
f.set(object, value);
}
private static Object read(String name, Object object) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Field f = MIC.getDeclaredField(name);
f.setAccessible(true);
return f.get(object);
}
public static void main(String[] args) {
LinkedHashSet<Integer> set = Stream.iterate(0, x->x+1)
.limit(10)
.collect(Collectors.toCollection(LinkedHashSet::new));
Iterator<Integer> iterator = set.iterator(); // un premier itérateur pour itérer sur le set
Iterator<Integer> saved=null; // cet itérateur va permettre de recommencer l'itératiion à partir du suivant de 5
Iterator<Integer> marked=null; // cet itérateur va permettre de recommencer l'itération à partir de 5
System.out.print("Set: ");
while(iterator.hasNext()) {
int i = iterator.next();
if( i==5 ) { // on a atteint 5
saved = saveIterator(iterator, false); // itérateur pour recommencer à itérer à partir de l'élément courant de iterator, exclus
marked = saveIterator(iterator, true); // itérateur pour recommencer à itérer à partir de l'élément courant de iterator, inclus
}
System.out.format("%d ",i);
}
System.out.println();
System.out.print("Saved: ");
while(saved.hasNext()) {
int i = saved.next();
System.out.format("%d ",i);
}
System.out.println();
Iterator<Integer> marked2=null; // un itérateur qui va permettre de recommencer l'itération à partir de 7
System.out.print("Marked: ");
while(marked.hasNext()) {
int i = marked.next();
System.out.format("%d ",i);
if( i==7 ) {
marked2 = saveIterator(marked, true);
}
}
System.out.println();
System.out.print("Marked 2: ");
while(marked2.hasNext()) {
int i = marked2.next();
System.out.format("%d ",i);
}
System.out.println();
}
} |
Partager