Ranides Atterwim 4 سال پیش
والد
کامیت
53899773d9
20فایلهای تغییر یافته به همراه322 افزوده شده و 37 حذف شده
  1. 12 5
      assira.commons/src/main/java/net/ranides/assira/collection/sets/IntAVLTreeMultiSet.java
  2. 12 4
      assira.commons/src/main/java/net/ranides/assira/collection/sets/IntRBTreeMultiSet.java
  3. 1 1
      assira.core/src/main/java/net/ranides/assira/collection/FlatCollection.java
  4. 14 0
      assira.core/src/main/java/net/ranides/assira/collection/lists/FlatList.java
  5. 2 2
      assira.core/src/main/java/net/ranides/assira/collection/maps/AOpenMap.java
  6. 68 0
      assira.core/src/main/java/net/ranides/assira/collection/maps/MapUtils.java
  7. 8 1
      assira.core/src/main/java/net/ranides/assira/collection/sets/AOpenSet.java
  8. 3 1
      assira.core/src/main/java/net/ranides/assira/collection/sets/ASortedSet.java
  9. 3 2
      assira.core/src/main/java/net/ranides/assira/collection/sets/CustomSet.java
  10. 33 1
      assira.core/src/main/java/net/ranides/assira/collection/sets/FlatSet.java
  11. 7 0
      assira.core/src/main/java/net/ranides/assira/collection/sets/IdentSet.java
  12. 26 3
      assira.core/src/main/java/net/ranides/assira/collection/sets/IntMultiSet.java
  13. 8 0
      assira.core/src/main/java/net/ranides/assira/collection/sets/IntSet.java
  14. 21 5
      assira.core/src/main/java/net/ranides/assira/collection/sets/IntSortedSet.java
  15. 1 0
      assira.core/src/main/java/net/ranides/assira/collection/sets/MaskFactory.java
  16. 52 4
      assira.core/src/main/java/net/ranides/assira/collection/sets/MultiSet.java
  17. 2 0
      assira.core/src/main/java/net/ranides/assira/collection/sets/OpenSet.java
  18. 3 0
      assira.core/src/main/java/net/ranides/assira/collection/sets/OrderedSet.java
  19. 26 6
      assira.core/src/main/java/net/ranides/assira/collection/sets/SetUtils.java
  20. 20 2
      assira.core/src/main/java/net/ranides/assira/collection/utils/CollectionSort.java

+ 12 - 5
assira.commons/src/main/java/net/ranides/assira/collection/sets/IntAVLTreeMultiSet.java

@@ -7,10 +7,9 @@
 package net.ranides.assira.collection.sets;
 
 import net.ranides.assira.collection.IntComparator;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.SortedSet;
+
+import java.util.*;
+
 import net.ranides.assira.collection.IntCollection;
 import net.ranides.assira.collection.arrays.ArrayAllocator;
 import net.ranides.assira.collection.iterators.IntIterator;
@@ -168,7 +167,15 @@ public class IntAVLTreeMultiSet extends AIntAVLTreeSet implements IntMultiSet {
             add(values[i]);
         }
     }
-    
+    @Override
+    public Collection<Integer> getAll(Object key) {
+        if(key instanceof Integer) {
+            return getAll((Integer) key);
+        } else {
+            return Collections.emptySet();
+        }
+    }
+
     @Override
     public IntCollection getAll(int key) {
         return subSet(key, key+1);

+ 12 - 4
assira.commons/src/main/java/net/ranides/assira/collection/sets/IntRBTreeMultiSet.java

@@ -7,10 +7,9 @@
 package net.ranides.assira.collection.sets;
 
 import net.ranides.assira.collection.IntComparator;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.SortedSet;
+
+import java.util.*;
+
 import net.ranides.assira.collection.IntCollection;
 import net.ranides.assira.collection.arrays.ArrayAllocator;
 import net.ranides.assira.collection.iterators.IntIterator;
@@ -164,6 +163,15 @@ public class IntRBTreeMultiSet extends AIntRBTreeSet implements IntMultiSet  {
         }
     }
 
+    @Override
+    public Collection<Integer> getAll(Object key) {
+        if(key instanceof Integer) {
+            return getAll((Integer) key);
+        } else {
+            return Collections.emptySet();
+        }
+    }
+
     @Override
     public IntCollection getAll(int key) {
         return subSet(key, key+1);

+ 1 - 1
assira.core/src/main/java/net/ranides/assira/collection/FlatCollection.java

@@ -68,7 +68,7 @@ public class FlatCollection<T> extends AbstractCollection<T> implements Serializ
      */
     @SafeVarargs
     public static <T> FlatCollection<T> of(Collection<T>... values) {
-        return new FlatCollection<T>().joinAll(Arrays.asList(values));
+        return new FlatCollection<T>(values);
     }
     /**
      * Inserts into view specified collection.

+ 14 - 0
assira.core/src/main/java/net/ranides/assira/collection/lists/FlatList.java

@@ -6,6 +6,8 @@
  */
 package net.ranides.assira.collection.lists;
 
+import net.ranides.assira.collection.sets.FlatSet;
+
 import java.io.Serializable;
 import java.util.*;
 import java.util.stream.Stream;
@@ -63,6 +65,18 @@ public class FlatList<T> extends AbstractSequentialList<T> implements Serializab
         this();
         joinAll(values);
     }
+
+    /**
+     * Creates merged view of provided collections
+     *
+     * @param values values
+     * @param <T> type
+     * @return view
+     */
+    @SafeVarargs
+    public static <T> FlatList<T> of(List<T>... values) {
+        return new FlatList<T>(values);
+    }
     
     /**
      * Inserts list at the end of merged view.

+ 2 - 2
assira.core/src/main/java/net/ranides/assira/collection/maps/AOpenMap.java

@@ -29,10 +29,10 @@ import java.util.Set;
  * This abstract class implements all public methods, but it does not define hashing strategy.
  * It uses <a href="https://en.wikipedia.org/wiki/Open_addressing">open addressing</a> internally.
  *
- * @author Ranides Atterwim {@literal <ranides@gmail.com>}
- *
  * @param <K> K
  * @param <V> V
+ *
+ * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 public abstract class AOpenMap<K,V> extends AMap<K, V> implements BlockMap<K, V>, java.io.Serializable {
    

+ 68 - 0
assira.core/src/main/java/net/ranides/assira/collection/maps/MapUtils.java

@@ -127,26 +127,94 @@ public class MapUtils {
         return new MMapWrapper<>(map, getter, setter);
     }
 
+    /**
+     * Returns read-only view which filters keys and maps them by provided function
+     *
+     * At access time it checks if provided key is accepted by "acceptor"
+     * At access time it maps accepted key by "function" and returns value from source map.
+     *
+     * @param content content
+     * @param acceptor acceptor
+     * @param function function
+     * @param <K> K
+     * @param <V> V
+     * @return view
+     */
     public static <K,V> Map<K,V> keyproxy(Supplier<Map<K, V>> content, Predicate<Object> acceptor, Function<K, K> function) {
         return new KeyMapAdapter<>(content, acceptor, function);
     }
 
+    /**
+     * It cretes read-only view of map which keys are created by provided functions.
+     * Maps keys at access time, before lookup.
+     *
+     * @param map map
+     * @param keyMapper keyMapper
+     * @param <TK> TK
+     * @param <RK> RK
+     * @param <V> V
+     * @return view
+     */
     public static <TK, RK, V> Map<RK,V> view(Map<TK, ? extends V> map, Function<TK, RK> keyMapper) {
         return view(map, keyMapper, Function.identity());
     }
 
+    /**
+     * It cretes read-only view of map which keys and values are created by provided functions.
+     * Maps keys at access time, before lookup.
+     * Maps values at access time, after lookup.
+     *
+     * @param map map
+     * @param keyMapper keyMapper
+     * @param valueMapper valueMapper
+     * @param <TK> TK
+     * @param <RK> RK
+     * @param <TV> TV
+     * @param <RV> RV
+     * @return view
+     */
     public static <TK, RK, TV, RV> Map<RK, RV> view(Map<TK,? extends TV> map, Function<TK, RK> keyMapper, Function<TV, RV> valueMapper) {
         return new ViewAdapter<>(map, keyMapper, valueMapper);
     }
 
+    /**
+     * Returns synchronized MultiMap
+     *
+     * @param map map
+     * @param <K> K
+     * @param <V> V
+     * @return MultiMap
+     */
     public static <K, V> MultiMap<K, V> synchronizedMultiMap(MultiMap<K, V> map) {
         return new SynchronizedMultiMap<>(map);
     }
 
+    /**
+     * Returns flattened map inserting flat result into OpenMap
+     * @param source
+     * @param joiner
+     * @return
+     */
     public static Map<String,Object> flat(Map<?,?> source, String joiner) {
         return flat(new OpenMap<>(), source, joiner);
     }
 
+    /**
+     * Returns flattened map.
+     *
+     * Every key inside provided map is converted into string.
+     * If source map contains any nested maps, their keys are converted to String too.
+     * Nested keys are concatenated using "joiner" as separator.
+     *
+     * Effectivelly, converts nested maps into flat maps with keys reflecting overall structure.
+     *
+     * Target map should be able to store any string mappings in efficient manner.
+     *
+     * @param target target
+     * @param source source
+     * @param joiner joiner
+     * @return map
+     */
     public static Map<String,Object> flat(Map<String,Object> target, Map<?,?> source, String joiner) {
         return flat(target, source, "", (a,b)->{
             if(StringTraits.isEmpty(a)) {

+ 8 - 1
assira.core/src/main/java/net/ranides/assira/collection/sets/AOpenSet.java

@@ -18,7 +18,14 @@ import net.ranides.assira.collection.utils.HashCollection;
 import net.ranides.assira.math.MathUtils;
 
 /**
- * A generic set map implementation
+ * A generic hash set implementation
+ *
+ * This abstract class implements all public methods, but it does not define hashing strategy.
+ * It uses <a href="https://en.wikipedia.org/wiki/Open_addressing">open addressing</a> internally.
+ *
+ * @param <K> K
+ *
+ * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 public abstract class AOpenSet<K> extends ASet<K> implements BlockCollection<K>, java.io.Serializable {
 

+ 3 - 1
assira.core/src/main/java/net/ranides/assira/collection/sets/ASortedSet.java

@@ -16,13 +16,15 @@ import net.ranides.assira.generic.CompareUtils;
 
 /**
  * An abstract class providing basic methods for sorted sets.
+ *
+ * @param <K> K
  */
 public abstract class ASortedSet<K> extends ASet<K> implements Set<K>, SortedSet<K>, java.io.Serializable {
 	
 	private static final long serialVersionUID = 1L;
 	
 	private final Comparator<? super K> acmp;
-    
+
     protected ASortedSet(Comparator<? super K> comparator) {
 		this.acmp = comparator;
     }

+ 3 - 2
assira.core/src/main/java/net/ranides/assira/collection/sets/CustomSet.java

@@ -14,8 +14,9 @@ import net.ranides.assira.collection.HashFunction;
 import net.ranides.assira.collection.arrays.ArrayAllocator;
 
 /**
- * A generic set map implementation whose
- * {@link HashFunction hashing strategy} isspecified at creation time.
+ * A generic set map implementation whose {@link HashFunction hashing strategy} is specified at creation time.
+ *
+ * @param <K> K
  */
 public final class CustomSet<K> extends AOpenSet<K> {
 

+ 33 - 1
assira.core/src/main/java/net/ranides/assira/collection/sets/FlatSet.java

@@ -15,6 +15,13 @@ import java.util.stream.Stream;
 
 /**
  * Dynamic view with elements from merged collections.
+ *
+ * It supports removing already inserted elements (if member collection supports it).
+ *
+ * It does not support adding new elements (because it is unknown which collection should be modified).
+ *
+ * Method {@link #contains} complexity is proportional to number of merged sets.
+ *
  * @param <T>
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
@@ -24,26 +31,51 @@ public class FlatSet<T> extends AbstractCollection<T> implements Set<T>, Seriali
 
     private final Collection<Set<T>> content = new LinkedList<>();
 
+    /**
+     * Creates empty flat set
+     */
     public FlatSet() {
         // do nothing
     }
 
+    /**
+     * Creates merged view of provided collections
+     *
+     * @param values values
+     */
     @SafeVarargs
     public FlatSet(Set<T>... values) {
         joinAll(Arrays.asList(values));
     }
 
+    /**
+     * Creates merged view of provided collections
+     *
+     * @param values values
+     */
     public FlatSet(Stream<Set<T>> values) {
         joinAll(values);
     }
 
+    /**
+     * Creates merged view of provided collections
+     *
+     * @param values values
+     */
     public FlatSet(Collection<Set<T>> values) {
         joinAll(values);
     }
 
+    /**
+     * Creates merged view of provided collections
+     *
+     * @param values values
+     * @param <T> type
+     * @return view
+     */
     @SafeVarargs
     public static <T> FlatSet<T> of(Set<T>... values) {
-        return new FlatSet<T>().joinAll(Arrays.asList(values));
+        return new FlatSet<T>(values);
     }
 
     /**

+ 7 - 0
assira.core/src/main/java/net/ranides/assira/collection/sets/IdentSet.java

@@ -15,6 +15,13 @@ import java.util.Iterator;
 
 /**
  * A generic set map implementation.
+ *
+ * It uses System.identityHashCode and compares objects by identity
+ *
+ * This class is not serializabe, as "identity relation" can't be established after
+ * recreation of map (keys will be completely new instances).
+ *
+ * @param <K> K
  */
 public class IdentSet<K> extends AOpenSet<K> {
 

+ 26 - 3
assira.core/src/main/java/net/ranides/assira/collection/sets/IntMultiSet.java

@@ -7,22 +7,44 @@
 package net.ranides.assira.collection.sets;
 
 import java.util.NoSuchElementException;
+import java.util.function.BinaryOperator;
 import java.util.function.IntBinaryOperator;
 import net.ranides.assira.collection.IntCollection;
 import net.ranides.assira.collection.lists.IntArrayList;
 
 /**
+ * Specialization of MultiSet using integer keys.
+ * Avoids unecessary boxing and unboxing operations.
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
-public interface IntMultiSet extends IntSet {
-    
+public interface IntMultiSet extends IntSet, MultiSet<Integer> {
+
+    /**
+     * non-generic version of method {@link #getAll(Object)}
+     *
+     * @param key key
+     * @return view
+     */
     IntCollection getAll(int key);
-    
+
+    /**
+     * non-generic version of method {@link #get(Object, BinaryOperator)}
+     *
+     * @param key key
+     * @param fold fold
+     * @return int
+     */
     default int get(int key, IntBinaryOperator fold) {
         return getAll(key).intstream().reduce(fold).orElseThrow(()->new NoSuchElementException());
     }
 
+    /**
+     * non-generic version of method {@link #removeAll(Object)}
+     *
+     * @param key key
+     * @return values
+     */
     default IntCollection removeAll(int key) {
         IntCollection out = new IntArrayList(getAll(key));
         for(int k : out) {
@@ -31,6 +53,7 @@ public interface IntMultiSet extends IntSet {
         return out;
     }
     
+    @Override
     default IntSet uniqueSet() {
         return new IntOpenSet(this);
     }

+ 8 - 0
assira.core/src/main/java/net/ranides/assira/collection/sets/IntSet.java

@@ -11,6 +11,8 @@ import net.ranides.assira.collection.IntCollection;
 import net.ranides.assira.collection.iterators.IntIterator;
 
 /**
+ * Specialization of Set for integer types.
+ * Avoids unecessary boxing and unboxing operations.
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
@@ -22,6 +24,12 @@ public interface IntSet extends IntCollection, Set<Integer> {
     @Override
     boolean rem(int k);
 
+    /**
+     * non-generic version of {@link #remove(Object)}
+     *
+     * @param k k
+     * @return bool
+     */
     boolean remove(int k);
     
 }

+ 21 - 5
assira.core/src/main/java/net/ranides/assira/collection/sets/IntSortedSet.java

@@ -12,6 +12,8 @@ import net.ranides.assira.collection.iterators.IntIterator;
 import net.ranides.assira.collection.iterators.IntListIterator;
 
 /**
+ * Specialization of SortedSet for integer types.
+ * Avoids unecessary boxing and unboxing operations.
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
@@ -21,12 +23,17 @@ public interface IntSortedSet extends IntSet, SortedSet<Integer> {
     IntComparator comparator();
 
     /**
-     * @see SortedSet#first()
+     * non-generic version of {@link #first()}
+     *
+     * @return int
      */
     int firstInt();
 
     /**
-     * @see SortedSet#headSet(Object)
+     * non-generic version of {@link #headSet(Integer)}
+     *
+     * @param end end
+     * @return view
      */
     IntSortedSet headSet(int end);
 
@@ -54,12 +61,18 @@ public interface IntSortedSet extends IntSet, SortedSet<Integer> {
     IntListIterator iterator(int begin);
 
     /**
-     * @see SortedSet#last()
+     * non-generic version of {@link #last()}
+     *
+     * @return int
      */
     int lastInt();
 
     /**
-     * @see SortedSet#subSet(Object,Object)
+     * non-generic version of {@link #subSet(Integer, Integer)}
+     *
+     * @param begin begin
+     * @param end end
+     * @return view
      */
     IntSortedSet subSet(int begin, int end);
 
@@ -67,7 +80,10 @@ public interface IntSortedSet extends IntSet, SortedSet<Integer> {
     IntSortedSet subSet(Integer begin, Integer end);
 
     /**
-     * @see SortedSet#tailSet(Object)
+     * non-generic version of {@link #tailSet(Integer)}
+     *
+     * @param begin begin
+     * @return view
      */
     IntSortedSet tailSet(int begin);
 

+ 1 - 0
assira.core/src/main/java/net/ranides/assira/collection/sets/MaskFactory.java

@@ -27,6 +27,7 @@ import net.ranides.assira.collection.sets.MaskSet.Mutable;
  * Every set returned by factory stores its content inside just one int.
  * Please note, that because of that, maximal number of distinct values is 32.
  *
+ * @param <T> T
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 public class MaskFactory<T> {

+ 52 - 4
assira.core/src/main/java/net/ranides/assira/collection/sets/MultiSet.java

@@ -13,20 +13,54 @@ import java.util.Set;
 import java.util.function.BinaryOperator;
 
 /**
+ * This is extension of Set interface with support for storing values more than once.
  *
+ * In some sense the whole idea looks strange, because "set" is a collection with unique elements.
+ * But in practice it is usefull because it allows for duplicated values and in the same time offers all
+ * performance characteristics of Set.
+ *
+ * It is complementary to MultiMap.
+ *
+ * @param <K> K
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 public interface MultiSet<K> extends Set<K> {
-    
+
+    /**
+     * Empty MultiSet
+     */
     @SuppressWarnings("rawtypes")
     MultiSet EMPTY = new SetUtils.EmptyMS();
-    
+
+    /**
+     * Returns view with all values equal to provided key
+     * It supports remove operation.
+     * It supports add operation (but obviously allows only inserting duplicates).
+     *
+     * @param key key
+     * @return view
+     */
     Collection<K> getAll(Object key);
-    
+
+    /**
+     * Finds all values equal to key and merges them using fold operator.
+     * For example, you can give "max" as fold operator.
+     *
+     * @param key key
+     * @param fold fold
+     * @return computed value
+     */
     default K get(Object key, BinaryOperator<K> fold) {
         return getAll(key).stream().reduce(fold).orElseThrow(()->new NoSuchElementException());
     }
 
+    /**
+     * Removes all values equal to specific key.
+     * Returns removed objects
+     *
+     * @param key key
+     * @return values
+     */
     default Collection<K> removeAll(Object key) {
         Collection<K> out = new ArrayList<>(getAll(key));
         for(K k : out) {
@@ -34,11 +68,25 @@ public interface MultiSet<K> extends Set<K> {
         }
         return out;
     }
-    
+
+    /**
+     * This method returns new Set with values from this collection.
+     * Returned Set won't duplicates.
+     *
+     * Please note: returned Set in NOT a view.
+     *
+     * @return new set
+     */
     default Set<K> uniqueSet() {
         return new OpenSet<>(this);
     }
 
+    /**
+     * Returns empty immutable MultiSet
+     *
+     * @param <K> K
+     * @return MultiSet
+     */
     @SuppressWarnings("unchecked")
     static <K> MultiSet<K> empty() {
         return EMPTY;

+ 2 - 0
assira.core/src/main/java/net/ranides/assira/collection/sets/OpenSet.java

@@ -14,6 +14,8 @@ import net.ranides.assira.generic.CompareUtils;
 
 /**
  * A generic set map implementation.
+ *
+ * @param <K> K
  */
 public final class OpenSet<K> extends AOpenSet<K> {
 

+ 3 - 0
assira.core/src/main/java/net/ranides/assira/collection/sets/OrderedSet.java

@@ -11,7 +11,10 @@ import java.util.Set;
 import java.util.Spliterator;
 
 /**
+ * This interface represents a list which preserves the order of elements
+ * and offers fast {@link #contains(Object)} method
  *
+ * @param <T> T
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 public interface OrderedSet<T> extends Set<T>, List<T> {

+ 26 - 6
assira.core/src/main/java/net/ranides/assira/collection/sets/SetUtils.java

@@ -12,24 +12,44 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.Set;
 import java.util.function.Function;
+
+import lombok.experimental.UtilityClass;
 import net.ranides.assira.collection.ACollection;
 import net.ranides.assira.collection.iterators.IteratorUtils;
 import net.ranides.assira.functional.covariant.ProjectionFunction;
 
 /**
+ * Static methods working with Sets
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
+@UtilityClass
 public final class SetUtils {
-    
-    private SetUtils() {
-        /* utility class */
-    }
-    
+
+    /**
+     * Creates view which transforms values stored inside source set.
+     * Returned view does not support modifications.
+     *
+     * @param set source set
+     * @param function mapping function
+     * @param <T> source type
+     * @param <R> target type
+     * @return read-only view
+     */
     public static <R,T> Set<R> map(Set<T> set, Function<? super T, ? extends R> function) {
         return new SetAdapter<>(set, function);
     }
-    
+
+    /**
+     * Creates view which transforms values stored inside source set.
+     * Returned view supports modifications: it uses passed projection for conversion in both directions.
+     *
+     * @param set source set
+     * @param function mapping projection
+     * @param <T> source type
+     * @param <R> target type
+     * @return mutable view
+     */
     public static <R,T> Set<R> map(Set<T> set, ProjectionFunction<T,R> function) {
         return new SetProjection<>(set, function);
     }

+ 20 - 2
assira.core/src/main/java/net/ranides/assira/collection/utils/CollectionSort.java

@@ -23,19 +23,37 @@ import java.util.List;
 
 /**
  * Those methods implement "group" sort.
- * Methods sort provided collections according to order established by comparator and first "leading" collections.
+ * Methods sort provided collections according to order established by comparator and first "leading" collection.
  */
 @UtilityClass
 public final class CollectionSort {
 
-    public static void isortArrays(IntComparator cmp, Object... collections) {
+    /**
+     * Sorts provided collections according to order established by comparator and first "leading" collection.
+     *
+     * @param cmp cmp
+     * @param collections collections
+     */
+    public static void sortIntArrays(IntComparator cmp, Object... collections) {
         NativeArraySort.quickSort(0, size(collections[0]), cmp, concat0(collections));
     }
 
+    /**
+     * Sorts provided collections according to order established by comparator and first "leading" collection.
+     *
+     * @param cmp cmp
+     * @param collections collections
+     */
     public static void sortArrays(Comparator<?> cmp, Object... collections) {
         NativeArraySort.quickSort(0, size(collections[0]), comparator(collections[0], cmp), concat0(collections));
     }
 
+    /**
+     * Creates concatenated swapper which swaps in one call elements inside all provided swappers
+     *
+     * @param swappers swappers
+     * @return swapper
+     */
     public static Swapper concat(Swapper... swappers) {
         return (a,b) -> {
             for(Swapper s : swappers) {