You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/05/08 12:58:24 UTC

[44/50] incubator-ignite git commit: # Remove unused methods from GridFunc.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/942abe45/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
index c86c5a4..6f544e0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
@@ -20,10 +20,8 @@ package org.apache.ignite.internal.util.lang;
 import org.apache.ignite.*;
 import org.apache.ignite.cluster.*;
 import org.apache.ignite.compute.*;
-import org.apache.ignite.events.*;
 import org.apache.ignite.internal.*;
 import org.apache.ignite.internal.util.*;
-import org.apache.ignite.internal.util.future.*;
 import org.apache.ignite.internal.util.typedef.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
 import org.apache.ignite.lang.*;
@@ -31,9 +29,6 @@ import org.jetbrains.annotations.*;
 import org.jsr166.*;
 
 import javax.cache.*;
-import java.io.*;
-import java.lang.reflect.*;
-import java.math.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
@@ -74,13 +69,6 @@ public class GridFunc {
     };
 
     /** */
-    private static final IgnitePredicate<Boolean> IDENTITY_PRED = new P1<Boolean>() {
-        @Override public boolean apply(Boolean e) {
-            return e;
-        }
-    };
-
-    /** */
     private static final IgnitePredicate<Object> ALWAYS_TRUE = new P1<Object>() {
         @Override public boolean apply(Object e) {
             return true;
@@ -128,34 +116,6 @@ public class GridFunc {
     };
 
     /** */
-    public static final IgnitePredicate<String> EMPTY_STRING = new P1<String>() {
-        @Override public boolean apply(String s) {
-            return isEmpty(s);
-        }
-    };
-
-    /** */
-    public static final IgnitePredicate<String> NOT_EMPTY_STRING = new P1<String>() {
-        @Override public boolean apply(String s) {
-            return !isEmpty(s);
-        }
-    };
-
-    /** */
-    public static final IgnitePredicate EMPTY_COLLECTION = new P1<Collection>() {
-        @Override public boolean apply(Collection c) {
-            return isEmpty(c);
-        }
-    };
-
-    /** */
-    public static final IgnitePredicate NOT_EMPTY_COLLECTION = new P1<Collection>() {
-        @Override public boolean apply(Collection c) {
-            return !isEmpty(c);
-        }
-    };
-
-    /** */
     private static final IgniteCallable<?> LIST_FACTORY = new IgniteCallable<List>() {
         @Override public List call() {
             return new ArrayList();
@@ -266,84 +226,6 @@ public class GridFunc {
     };
 
     /** */
-    private static final IgniteInClosure<?> PRINTLN = new CI1() {
-        @Override public void apply(Object o) {
-            System.out.println(o);
-        }
-
-        @Override public String toString() {
-            return "Print line closure.";
-        }
-    };
-
-    /** */
-    private static final IgniteInClosure<?> PRINT = new CI1() {
-        @Override public void apply(Object o) {
-            System.out.print(o);
-        }
-
-        @Override public String toString() {
-            return "Print closure.";
-        }
-    };
-
-    /** */
-    private static final IgniteOutClosure<?> NILL = new CO() {
-        @Nullable @Override public Object apply() {
-            return null;
-        }
-
-        @Override public String toString() {
-            return "Nill closure.";
-        }
-    };
-
-    /** */
-    private static final IgniteClosure<Runnable, GridAbsClosure> R2C = new C1<Runnable, GridAbsClosure>() {
-        @Override public GridAbsClosure apply(Runnable r) {
-            return as(r);
-        }
-
-        @Override public String toString() {
-            return "Runnable to absolute closure transformer.";
-        }
-    };
-
-    /** */
-    private static final IgniteClosure<ClusterGroup, IgnitePredicate<ClusterNode>> P2P =
-        new C1<ClusterGroup, IgnitePredicate<ClusterNode>>() {
-            @Override public IgnitePredicate<ClusterNode> apply(ClusterGroup e) {
-                return e.predicate();
-            }
-
-            @Override public String toString() {
-                return "Projection to its predicate transformer closure.";
-            }
-    };
-
-    /** */
-    private static final IgniteClosure<Object, Class<?>> CLAZZ = new C1<Object, Class<?>>() {
-        @Override public Class<?> apply(Object o) {
-            return o.getClass();
-        }
-
-        @Override public String toString() {
-            return "Object to class transformer closure.";
-        }
-    };
-
-    /** */
-    private static final IgniteClosure MAP_ENTRY_KEY = new IgniteClosure() {
-        @Override public Object apply(Object o) {
-            return ((Map.Entry)o).getKey();
-        }
-
-        @Override public String toString() {
-            return "Map entry to key transformer closure.";
-        }
-    };
-
-    /** */
     private static final IgniteClosure CACHE_ENTRY_KEY = new IgniteClosure() {
         @Override public Object apply(Object o) {
             return ((Cache.Entry)o).getKey();
@@ -354,16 +236,6 @@ public class GridFunc {
         }
     };
 
-    /** */
-    private static final IgniteClosure MAP_ENTRY_VAL = new IgniteClosure() {
-        @Override public Object apply(Object o) {
-            return ((Map.Entry)o).getValue();
-        }
-
-        @Override public String toString() {
-            return "Map entry to value transformer closure.";
-        }
-    };
 
     /** */
     private static final IgniteClosure CACHE_ENTRY_VAL_GET = new IgniteClosure() {
@@ -390,18 +262,6 @@ public class GridFunc {
     };
 
     /** */
-    private static final IgnitePredicate CACHE_ENTRY_NO_PEEK_VAL = new IgnitePredicate() {
-        @SuppressWarnings({"unchecked"})
-        @Override public boolean apply(Object o) {
-            return ((Cache.Entry)o).getValue() == null;
-        }
-
-        @Override public String toString() {
-            return "Cache entry no-peek-value predicate.";
-        }
-    };
-
-    /** */
     private static final IgniteClosure<ClusterNode, UUID> NODE2ID = new IgniteClosure<ClusterNode, UUID>() {
         @Override public UUID apply(ClusterNode n) {
             return n.id();
@@ -442,44 +302,6 @@ public class GridFunc {
     };
 
     /**
-     * Gets breaker predicate which will return a predicate that will
-     * evaluate to {@code firstVal} when checked the first time,
-     * but then will always evaluate to the opposite value.
-     *
-     * @param firstVal First value.
-     * @param <T> Predicate type.
-     * @return Breaker predicate.
-     */
-    public static <T> IgnitePredicate<T> breaker(final boolean firstVal) {
-        return new IgnitePredicate<T>() {
-            private boolean b = true;
-
-            @Override public boolean apply(T e) {
-                if (b) {
-                    b = false;
-
-                    return firstVal;
-                }
-
-                return !firstVal;
-            }
-
-            @Override public String toString() {
-                return "Breaker predicate.";
-            }
-        };
-    }
-
-    /**
-     * Gets closure that transform a grid projection into its predicate.
-     *
-     * @return Closure transforming a grid projection into its predicate.
-     */
-    public static IgniteClosure<ClusterGroup, IgnitePredicate<ClusterNode>> predicate() {
-        return P2P;
-    }
-
-    /**
      * Gets predicate that evaluates to {@code true} only for given local node ID.
      *
      * @param locNodeId Local node ID.
@@ -510,4868 +332,2608 @@ public class GridFunc {
     }
 
     /**
-     * Returns out closure that always returns {@code null}.
-     *
-     * @return Out closure that always returns {@code null}.
-     */
-    @SuppressWarnings("unchecked")
-    public static <T> IgniteOutClosure<T> nill() {
-        return (IgniteOutClosure<T>)NILL;
-    }
-
-    /**
-     * Creates closure that will reflectively call a method with the given name on
-     * closure's argument and return result of that call.
-     * <p>
-     * Method reflects the typedef for {@link org.apache.ignite.lang.IgniteClosure} which is {@link C1}.
+     * Creates new collection by removing duplicates from the given collection.
      *
-     * @param mtdName Method name.
-     * @param args Optional set of arguments for the method call.
-     * @param <R> Type of closure return value.
-     * @param <T> Type of closure argument.
-     * @return Reflective closure.
-     * @throws GridClosureException Thrown in case of any reflective invocation errors.
+     * @param c Collection to remove duplicates from.
+     * @param <T> Type of the collection.
+     * @return De-duped collection.
      */
-    public static <T, R> IgniteClosure<T, R> cInvoke(final String mtdName, final Object... args) {
-        A.notNull(mtdName, "mtdName");
-
-        return new C1<T, R>() {
-            private Method mtd;
+    public static <T> Collection<T> dedup(Collection<? extends T> c) {
+        A.notNull(c, "c");
 
-            @SuppressWarnings("unchecked")
-            @Override public R apply(T t) {
-                try {
-                    // No synchronization allows for double creation - ignoring...
-                    if (mtd == null) {
-                        mtd = method(t.getClass(), mtdName, args);
+        Collection<T> set = new GridLeanSet<>();
 
-                        mtd.setAccessible(true);
-                    }
+        set.addAll(c);
 
-                    return (R)mtd.invoke(t, args);
-                }
-                catch (Exception e) {
-                    throw wrap(e);
-                }
-            }
-        };
+        return set;
     }
 
     /**
-     * Creates in closure that will reflectively call a method with the given name on
-     * closure's argument.
+     * Calculates sum of all elements.
      * <p>
-     * Method reflects the typedef for {@link org.apache.ignite.lang.IgniteClosure} which is {@link C1}.
+     * <img src="{@docRoot}/img/sum.png">
      *
-     * @param mtdName Method name.
-     * @param args Optional set of arguments for the method call.
-     * @param <T> Type of closure argument.
-     * @return Reflective in closure.
-     * @throws GridClosureException Thrown in case of any reflective invocation errors.
+     * @param c Collection of elements.
+     * @return Sum of all elements.
      */
-    public static <T> IgniteInClosure<T> ciInvoke(final String mtdName, final Object... args) {
-        A.notNull(mtdName, "mtdName");
-
-        return new CI1<T>() {
-            private Method mtd;
+    public static int sumInt(Iterable<Integer> c) {
+        A.notNull(c, "c");
 
-            @Override public void apply(T t) {
-                try {
-                    // No synchronization allows for double creation - ignoring...
-                    if (mtd == null) {
-                        mtd = method(t.getClass(), mtdName, args);
+        int sum = 0;
 
-                        mtd.setAccessible(true);
-                    }
+        for (int t : c)
+            sum += t;
 
-                    mtd.invoke(t, args);
-                }
-                catch (Exception e) {
-                    throw wrap(e);
-                }
-            }
-        };
+        return sum;
     }
 
     /**
-     * Creates out closure that will reflectively call a method with the given name on provided
-     * object and return result of that call.
-     * <p>
-     * Method reflects the typedef for {@link org.apache.ignite.lang.IgniteOutClosure} which is {@link CO}.
+     * Gets reducer which always returns {@code true} from {@link org.apache.ignite.lang.IgniteReducer#collect(Object)}
+     * method and passed in {@code element} from {@link org.apache.ignite.lang.IgniteReducer#reduce()} method.
      *
-     * @param o Target object to call the method on.
-     * @param mtdName Method name.
-     * @param args Optional set of arguments for the method call.
-     * @param <R> Type of closure return value.
-     * @return Reflective out closure.
-     * @throws GridClosureException Thrown in case of any reflective invocation errors.
+     * @param elem Element to return from {@link org.apache.ignite.lang.IgniteReducer#reduce()} method.
+     * @param <T> Reducer element type.
+     * @return Passed in element.
      */
-    public static <R> IgniteOutClosure<R> coInvoke(final Object o, final String mtdName, final Object... args) {
-        A.notNull(o, "o", mtdName, "mtdName");
-
-        return new CO<R>() {
-            private Method mtd;
-
-            @SuppressWarnings("unchecked")
-            @Override public R apply() {
-                try {
-                    // No synchronization allows for double creation - ignoring...
-                    if (mtd == null) {
-                        mtd = method(o.getClass(), mtdName, args);
-
-                        mtd.setAccessible(true);
-                    }
+    public static <T> IgniteReducer<T, T> identityReducer(final T elem) {
+        return new R1<T, T>() {
+            @Override public boolean collect(T e) {
+                return true;
+            }
 
-                    return (R)mtd.invoke(o, args);
-                }
-                catch (Exception e) {
-                    throw wrap(e);
-                }
+            @Override public T reduce() {
+                return elem;
             }
         };
     }
 
     /**
-     * Creates absolute closure that will reflectively call a method with the given name on provided object.
+     * Gets reducer closure that calculates sum of integer elements.
      * <p>
-     * Method reflects the typedef for {@link GridAbsClosure} which is {@link CA}.
+     * <img src="{@docRoot}/img/sum.png">
      *
-     * @param o Target object to call the method on.
-     * @param mtdName Method name.
-     * @param args Optional set of arguments for the method call.
-     * @return Reflective absolute closure.
-     * @throws GridClosureException Thrown in case of any reflective invocation errors.
+     * @return Reducer that calculates sum of integer elements.
      */
-    public static GridAbsClosure caInvoke(final Object o, final String mtdName, @Nullable final Object... args) {
-        A.notNull(o, "o", mtdName, "mtdName");
-
-        return new CA() {
-            /** */
-            private Method mtd;
+    public static IgniteReducer<Integer, Integer> sumIntReducer() {
+        return new R1<Integer, Integer>() {
+            private AtomicInteger sum = new AtomicInteger(0);
 
-            @SuppressWarnings("unchecked")
-            @Override public void apply() {
-                try {
-                    // No synchronization allows for double creation - ignoring...
-                    if (mtd == null) {
-                        mtd = method(o.getClass(), mtdName, args);
+            @Override public boolean collect(Integer e) {
+                if (e != null)
+                    sum.addAndGet(e);
 
-                        mtd.setAccessible(true);
-                    }
+                return true;
+            }
 
-                    mtd.invoke(o, args);
-                }
-                catch (Exception e) {
-                    throw wrap(e);
-                }
+            @Override public Integer reduce() {
+                return sum.get();
             }
         };
     }
 
     /**
-     * Creates out closure that will reflectively call a static method with the given name
-     * and return result of that call.
+     * Gets reducer closure that calculates sum of long integer elements.
      * <p>
-     * Method reflects the typedef for {@link org.apache.ignite.lang.IgniteOutClosure} which is {@link CO}.
+     * <img src="{@docRoot}/img/sum.png">
      *
-     * @param cls Class to call a static method on.
-     * @param mtdName Method name.
-     * @param args Optional set of arguments for the method call.
-     * @param <R> Type of closure return value.
-     * @return Reflective out closure.
-     * @throws GridClosureException Thrown in case of any reflective invocation errors.
+     * @return Reducer that calculates sum of long integer elements.
      */
-    public static <R> IgniteOutClosure<R> coInvoke(final Class<?> cls, final String mtdName,
-        @Nullable final Object... args) {
-        A.notNull(cls, "cls", mtdName, "mtdName");
-
-        return new CO<R>() {
-            /** */
-            private Method mtd;
+    public static IgniteReducer<Long, Long> sumLongReducer() {
+        return new R1<Long, Long>() {
+            private AtomicLong sum = new AtomicLong(0);
 
-            @SuppressWarnings("unchecked")
-            @Override public R apply() {
-                try {
-                    // No synchronization allows for double creation - ignoring...
-                    if (mtd == null) {
-                        mtd = method(cls, mtdName, args);
+            @Override public boolean collect(Long e) {
+                if (e != null)
+                    sum.addAndGet(e);
 
-                        mtd.setAccessible(true);
-                    }
+                return true;
+            }
 
-                    return (R)mtd.invoke(null, args);
-                }
-                catch (Exception e) {
-                    throw wrap(e);
-                }
+            @Override public Long reduce() {
+                return sum.get();
             }
         };
     }
 
     /**
-     * Creates absolute closure that will reflectively call a static method with the given name.
-     * <p>
-     * Method reflects the typedef for {@link GridAbsClosure} which is {@link CA}.
+     * Creates a range list containing numbers in given range.
      *
-     * @param cls Class to call a static method on.
-     * @param mtdName Method name.
-     * @param args Optional set of arguments for the method call.
-     * @return Reflective absolute closure.
-     * @throws GridClosureException Thrown in case of any reflective invocation errors.
+     * @param fromIncl Inclusive start of the range.
+     * @param toExcl Exclusive stop of the range.
+     * @return List containing numbers in range.
      */
-    public static GridAbsClosure caInvoke(final Class<?> cls, final String mtdName, @Nullable final Object... args) {
-        A.notNull(cls, "cls", mtdName, "mtdName");
+    public static List<Integer> range(int fromIncl, int toExcl) {
+        A.ensure(fromIncl >= 0, "fromIncl >= 0");
+        A.ensure(toExcl >= 0, "toExcl >= 0");
+        A.ensure(toExcl >= fromIncl, "toExcl > fromIncl");
 
-        return new CA() {
-            /** */
-            private Method mtd;
+        if (toExcl == fromIncl)
+            return Collections.emptyList();
 
-            @SuppressWarnings("unchecked")
-            @Override public void apply() {
-                try {
-                    // No synchronization allows for double creation - ignoring...
-                    if (mtd == null) {
-                        mtd = method(cls, mtdName, args);
+        List<Integer> list = new ArrayList<>(toExcl - fromIncl);
 
-                        mtd.setAccessible(true);
-                    }
+        for (int i = fromIncl; i < toExcl; i++)
+            list.add(i);
 
-                    mtd.invoke(null, args);
-                }
-                catch (Exception e) {
-                    throw wrap(e);
-                }
-            }
-        };
+        return list;
     }
 
     /**
-     * Looks up the method with given parameters.
+     * Gets reducer closure that concatenates strings using provided delimiter.
      *
-     * @param cls Class to look up in.
-     * @param mtdName Method name to look up.
-     * @param args Optional set of method parameters.
-     * @return Method instance.
-     * @throws Exception Thrown in case of any reflective errors.
+     * @param delim Delimiter (optional).
+     * @return Reducer that concatenates strings using provided delimeter.
      */
-    private static Method method(Class<?> cls, String mtdName, @Nullable Object... args) throws Exception {
-        assert cls != null;
-        assert mtdName != null;
-
-        int cnt = 0;
-
-        Method m = null;
-
-        for (Method mtd : cls.getDeclaredMethods())
-            if (mtd.getName().equals(mtdName)) {
-                cnt++;
-
-                m = mtd;
-            }
+    public static IgniteReducer<String, String> concatReducer(@Nullable final String delim) {
+        return new R1<String, String>() {
+            private SB sb = new SB();
 
-        if (cnt == 0)
-            throw new NoSuchMethodException(cls.getName() + '#' + mtdName);
+            private boolean first = true;
 
-        // If there is only one method with provided name we
-        // don't use lookup that requires parameters' types since
-        // it is a lot more complex to deal with type inheritance there.
-        if (cnt == 1)
-            return m;
+            private final Object lock = new Object();
 
-        if (!isEmpty(args)) {
-            assert args != null;
+            @Override public boolean collect(String s) {
+                synchronized (lock) {
+                    if (!first && !isEmpty(delim))
+                        sb.a(delim);
 
-            Class<?>[] types = new Class[args.length];
+                    sb.a(s);
 
-            int i = 0;
+                    first = false;
+                }
 
-            for (Object arg : args) {
-                // This is not going to work in cases when method expects
-                // an interface or supertype. Accept this limitation for now...
-                types[i++] = arg.getClass();
+                return true;
             }
 
-            return cls.getDeclaredMethod(mtdName, types);
-        }
-        else
-            return cls.getDeclaredMethod(mtdName);
+            @Override public String reduce() {
+                synchronized (lock) {
+                    return sb.toString();
+                }
+            }
+        };
     }
 
     /**
-     * Gets closure that converts object to its runtime class.
+     * Concatenates strings using provided delimiter.
      *
-     * @return Closure that converts object to its runtime class.
-     */
-    public static IgniteClosure<Object, Class<?>> clazz() {
-        return CLAZZ;
-    }
-
-    /**
-     * Creates new collection by removing duplicates from the given collection.
-     *
-     * @param c Collection to remove duplicates from.
-     * @param <T> Type of the collection.
-     * @return De-duped collection.
+     * @param c Input collection.
+     * @param delim Delimiter (optional).
+     * @return Concatenated string.
      */
-    public static <T> Collection<T> dedup(Collection<? extends T> c) {
+    public static String concat(Iterable<String> c, @Nullable String delim) {
         A.notNull(c, "c");
 
-        Collection<T> set = new GridLeanSet<>();
-
-        set.addAll(c);
-
-        return set;
+        return reduce(c, concatReducer(delim));
     }
 
     /**
-     * Calculates sum of all elements.
+     * Gets collections of data items from grid job res casted to specified type.
      * <p>
-     * <img src="{@docRoot}/img/sum.png">
-     *
-     * @param c Collection of elements.
-     * @return Sum of all elements.
-     */
-    public static int sumInt(Iterable<Integer> c) {
-        A.notNull(c, "c");
-
-        int sum = 0;
-
-        for (int t : c) {
-            sum += t;
-        }
-
-        return sum;
-    }
-
-    /**
-     * Calculates sum of all elements.
+     * Here's the typical example of how this method is used in {@code reduce()} method
+     * implementation (this example sums up all the values of {@code Integer} type):
+     * <pre name="code" class="java">
+     * public Integer reduce(List&lt;GridComputeJobResult&gt; res) throws IgniteCheckedException {
+     *     return F.sum(F.&lt;Integer&gt;jobResults(res));
+     * }
+     * </pre>
      * <p>
-     * <img src="{@docRoot}/img/sum.png">
+     * Note that this method doesn't create a new collection but simply iterates over the input one.
      *
-     * @param c Collection of elements.
-     * @return Sum of all elements.
+     * @param res Collection of grid job res.
+     * @param <T> Type of the data item to cast to. See {@link org.apache.ignite.compute.ComputeJobResult#getData()} method.
+     * @return Collections of data items casted to type {@code T}.
+     * @see org.apache.ignite.compute.ComputeJobResult#getData()
      */
-    public static double sumDouble(Iterable<Double> c) {
-        A.notNull(c, "c");
+    public static <T> Collection<T> jobResults(@Nullable Collection<? extends ComputeJobResult> res) {
+        if (isEmpty(res))
+            return Collections.emptyList();
 
-        double sum = 0;
+        assert res != null;
 
-        for (double t : c) {
-            sum += t;
-        }
+        Collection<T> c = new ArrayList<>(res.size());
 
-        return sum;
+        for (ComputeJobResult r : res)
+            c.add(r.<T>getData());
+
+        return c;
     }
 
     /**
-     * Calculates sum of all elements.
+     * Convenient utility method that returns collection of node IDs for a given
+     * collection of grid nodes.
      * <p>
-     * <img src="{@docRoot}/img/sum.png">
+     * Note that this method doesn't create a new collection but simply iterates
+     * over the input one.
      *
-     * @param c Collection of elements.
-     * @return Sum of all elements.
+     * @param nodes Collection of grid nodes.
+     * @return Collection of node IDs for given collection of grid nodes.
      */
-    public static BigDecimal sumBigDecimal(Iterable<BigDecimal> c) {
-        A.notNull(c, "c");
-
-        BigDecimal sum = BigDecimal.ZERO;
-
-        for (BigDecimal t : c) {
-            sum = sum.add(t);
-        }
+    public static Collection<UUID> nodeIds(@Nullable Collection<? extends ClusterNode> nodes) {
+        if (nodes == null || nodes.isEmpty())
+            return Collections.emptyList();
 
-        return sum;
+        return F.viewReadOnly(nodes, node2id());
     }
 
     /**
-     * Calculates sum of all elements.
+     * Convenient utility method that returns collection of node ID8s for a given
+     * collection of grid nodes. ID8 is a shorter string representation of node ID,
+     * mainly the first 8 characters.
      * <p>
-     * <img src="{@docRoot}/img/sum.png">
+     * Note that this method doesn't create a new collection but simply iterates
+     * over the input one.
      *
-     * @param c Collection of elements.
-     * @return Sum of all elements.
+     * @param nodes Collection of grid nodes.
+     * @return Collection of node IDs for given collection of grid nodes.
      */
-    public static BigInteger sumBigInt(Iterable<BigInteger> c) {
-        A.notNull(c, "c");
-
-        BigInteger sum = BigInteger.ZERO;
-
-        for (BigInteger t : c) {
-            sum = sum.add(t);
-        }
+    public static Collection<String> nodeId8s(@Nullable Collection<? extends ClusterNode> nodes) {
+        if (nodes == null || nodes.isEmpty())
+            return Collections.emptyList();
 
-        return sum;
+        return F.viewReadOnly(nodes, NODE2ID8);
     }
 
     /**
-     * Calculates arithmetic mean.
+     * Convenient utility method that returns collection of node ID8s for a given
+     * collection of node IDs. ID8 is a shorter string representation of node ID,
+     * mainly the first 8 characters.
      * <p>
-     * <img src="{@docRoot}/img/avg.png">
+     * Note that this method doesn't create a new collection but simply iterates
+     * over the input one.
      *
-     * @param c Input collection.
-     * @return Arithmetic mean of the input collection.
+     * @param ids Collection of nodeIds.
+     * @return Collection of node IDs for given collection of grid nodes.
      */
-    public static double avg(Iterable<? extends Number> c) {
-        A.notNull(c, "c");
-
-        double sum = 0;
-
-        int i = 0;
-
-        for (Number t : c) {
-            sum += t.doubleValue();
-
-            i++;
-        }
+    public static Collection<String> id8s(@Nullable Collection<UUID> ids) {
+        if (ids == null || ids.isEmpty())
+            return Collections.emptyList();
 
-        return sum / i;
+        return F.viewReadOnly(ids, ID2ID8);
     }
 
     /**
-     * Gets reducer closure that calculates arithmetic mean.
-     * <p>
-     * <img src="{@docRoot}/img/avg.png">
+     * Creates absolute closure that does <tt>System.out.println(msg)</tt>.
      *
-     * @return Reducer closure that calculated arithmetic mean.
+     * @param msg Message to print.
+     * @return Absolute closure that print message.
      */
-    public static <T extends Number> IgniteReducer<T, Double> avgReducer() {
-        return new R1<T, Double>() {
-            private double sum;
-            private int i;
-
-            private final Object lock = new Object();
-
-            @Override public boolean collect(T e) {
-                if (e != null)
-                    synchronized (lock) {
-                        sum += e.doubleValue();
-                        i++;
-                    }
-
-                return true;
-            }
-
-            @Override public Double reduce() {
-                synchronized (lock) {
-                    return sum / i;
-                }
+    public static GridAbsClosure println(final String msg) {
+        return new CA() {
+            @Override public void apply() {
+                System.out.println(msg);
             }
         };
     }
 
     /**
-     * Calculates quadratic mean.
-     * <p>
-     * <img src="{@docRoot}/img/qavg.png">
+     * Gets random value from given collection.
      *
-     * @param c Input collection.
-     * @return Quadratic mean of the input collection.
+     * @param c Input collection (no {@code null} and not emtpy).
+     * @param <T> Type of the collection.
+     * @return Random value from the input collection.
      */
-    public static double qavg(Iterable<? extends Number> c) {
+    @SuppressWarnings("UnusedDeclaration")
+    public static <T> T rand(Collection<? extends T> c) {
         A.notNull(c, "c");
 
-        double sum = 0;
+        int n = ThreadLocalRandom8.current().nextInt(c.size());
 
         int i = 0;
 
-        for (Number t : c) {
-            double d = t.doubleValue();
-
-            sum += d * d;
-
-            i++;
+        for (T t : c) {
+            if (i++ == n)
+                return t;
         }
 
-        return Math.sqrt(sum / i);
+        throw new ConcurrentModificationException();
     }
 
     /**
-     * Gets reducer closure that calculates quadratic mean.
-     * <p>
-     * <img src="{@docRoot}/img/qavg.png">
+     * Gets random value from given list. For random-access lists this
+     * operation is O(1), otherwise O(n).
      *
-     * @return Reducer closure that calculated quadratic mean.
+     * @param l Input collection.
+     * @param <T> Type of the list elements.
+     * @return Random value from the input list.
      */
-    public static <T extends Number> IgniteReducer<T, Double> qavgReducer() {
-        return new R1<T, Double>() {
-            private double sum;
-            private int i;
-
-            private final Object lock = new Object();
-
-            @Override public boolean collect(T e) {
-                if (e != null) {
-                    double d = e.doubleValue();
-
-                    synchronized (lock) {
-                        sum += d * d;
-
-                        i++;
-                    }
-                }
-
-                return true;
-            }
+    public static <T> T rand(List<T> l) {
+        A.notNull(l, "l");
 
-            @Override public Double reduce() {
-                synchronized (lock) {
-                    return Math.sqrt(sum / i);
-                }
-            }
-        };
+        return l.get(ThreadLocalRandom8.current().nextInt(l.size()));
     }
 
     /**
-     * Calculates geometric mean.
-     * <p>
-     * <img src="{@docRoot}/img/gavg.png">
+     * Gets random value from given array. This operation
+     * does not iterate through array elements and returns immediately.
      *
      * @param c Input collection.
-     * @return Geometric mean of the input collection.
+     * @param <T> Type of the collection.
+     * @return Random value from the input collection.
      */
-    public static double gavg(Iterable<? extends Number> c) {
+    public static <T> T rand(T... c) {
         A.notNull(c, "c");
 
-        double sum = 0;
-
-        int i = 0;
-
-        for (Number t : c) {
-            sum *= t.doubleValue();
-
-            i++;
-        }
-
-        return Math.pow(sum, 1f / i);
+        return c[ThreadLocalRandom8.current().nextInt(c.length)];
     }
 
     /**
-     * Gets reducer closure that calculates geometric mean.
-     * <p>
-     * <img src="{@docRoot}/img/gavg.png">
+     * Concatenates an element to a collection. If {@code copy} flag is {@code true}, then
+     * a new collection will be created and the element and passed in collection will be
+     * copied into the new one. The returned collection will be modifiable. If {@code copy}
+     * flag is {@code false}, then a read-only view will be created over the element and given
+     * collections and no copying will happen.
      *
-     * @return Reducer closure that calculated geometric mean.
+     * @param cp Copy flag.
+     * @param t First element.
+     * @param c Second collection.
+     * @param <T> Element type.
+     * @return Concatenated collection.
      */
-    public static <T extends Number> IgniteReducer<T, Double> gavgReducer() {
-        return new R1<T, Double>() {
-            private double sum;
-            private int i;
+    public static <T> Collection<T> concat(boolean cp, @Nullable final T t, @Nullable final Collection<T> c) {
+        if (cp) {
+            if (isEmpty(c)) {
+                Collection<T> l = new ArrayList<>(1);
 
-            private final Object lock = new Object();
+                l.add(t);
 
-            @Override public boolean collect(T e) {
-                if (e != null)
-                    synchronized (lock) {
-                        sum *= e.doubleValue();
+                return l;
+            }
 
-                        i++;
-                    }
+            assert c != null;
 
-                return true;
-            }
+            Collection<T> ret = new ArrayList<>(c.size() + 1);
 
-            @Override public Double reduce() {
-                synchronized (lock) {
-                    return Math.pow(sum, 1f / i);
-                }
-            }
-        };
-    }
+            ret.add(t);
+            ret.addAll(c);
 
-    /**
-     * Calculates weighted mean.
-     * <p>
-     * <img src="{@docRoot}/img/wavg.png">
-     *
-     * @param c Collection of elements.
-     * @param w Collection of weights.
-     * @return Weighted mean of the input collection.
-     */
-    public static double wavg(Collection<? extends Number> c, Collection<? extends Number> w) {
-        A.notNull(c, "c", w, "w");
-        A.ensure(c.size() == w.size(), "c.size() == w.size()");
+            return ret;
+        }
+        else {
+            if (isEmpty(c))
+                return Collections.singletonList(t);
 
-        double sumC = 0;
-        double sumW = 0;
+            assert c != null;
 
-        Iterator<? extends Number> iterC = c.iterator();
-        Iterator<? extends Number> iterW = w.iterator();
+            return new GridSerializableCollection<T>() {
+                @NotNull
+                @Override public Iterator<T> iterator() {
+                    return new GridSerializableIterator<T>() {
+                        private Iterator<T> it;
 
-        while (iterC.hasNext()) {
-            assert iterW.hasNext();
+                        @Override public boolean hasNext() {
+                            return it == null || it.hasNext();
+                        }
 
-            double dc = iterC.next().doubleValue();
-            double dw = iterW.next().doubleValue();
+                        @Nullable @Override public T next() {
+                            if (it == null) {
+                                it = c.iterator();
 
-            sumW += dw;
-            sumC += dw * dc;
-        }
+                                return t;
+                            }
 
-        return sumC / sumW;
-    }
+                            return it.next();
+                        }
 
-    /**
-     * Calculates harmonic mean.
-     * <p>
-     * <img src="{@docRoot}/img/havg.png">
+                        @Override public void remove() {
+                            throw new UnsupportedOperationException();
+                        }
+                    };
+                }
+
+                @Override public int size() {
+                    return c.size() + 1;
+                }
+
+                @Override public boolean equals(Object obj) {
+                    return obj instanceof Collection && eqNotOrdered(this, (Collection)obj);
+                }
+            };
+        }
+    }
+
+    /**
+     * Concatenates 2 collections into one. If {@code copy} flag is {@code true}, then
+     * a new collection will be created and these collections will be copied into the
+     * new one. The returned collection will be modifiable. If {@code copy} flag is
+     * {@code false}, then a read-only view will be created over given collections
+     * and no copying will happen.
      *
-     * @param c Input collection.
-     * @return Harmonic mean of the input collection.
+     * @param cp Copy flag.
+     * @param c1 First collection.
+     * @param c2 Second collection.
+     * @param <T> Element type.
+     * @return Concatenated {@code non-null} collection.
      */
-    public static double havg(Iterable<? extends Number> c) {
-        A.notNull(c, "c");
+    public static <T> Collection<T> concat(boolean cp, @Nullable final Collection<T> c1,
+        @Nullable final Collection<T> c2) {
+        if (cp) {
+            if (isEmpty(c1) && isEmpty(c2))
+                return new ArrayList<>(0);
 
-        double sum = 0;
+            if (isEmpty(c1))
+                return new ArrayList<>(c2);
 
-        int i = 0;
+            if (isEmpty(c2))
+                return new ArrayList<>(c1);
 
-        for (Number t : c) {
+            Collection<T> c = new ArrayList<>(c1.size() + c2.size());
 
-            sum += 1 / t.doubleValue();
+            c.addAll(c1);
+            c.addAll(c2);
 
-            i++;
+            return c;
         }
+        else {
+            if (isEmpty(c1) && isEmpty(c2))
+                return Collections.emptyList();
 
-        return i / sum;
-    }
-
-    /**
-     * Gets reducer closure that collects only a single value and returns it
-     * without any transformations.
-     *
-     * @return Reducer closure that collects and returns single value.
-     */
-    public static <T> IgniteReducer<T, T> singleReducer() {
-        return new R1<T, T>() {
-            private T obj;
+            if (isEmpty(c1) || isEmpty(c2)) {
+                Collection<T> c = isEmpty(c1) ? c2 : c1;
 
-            @Override public boolean collect(T e) {
-                // No synchronization needed here.
-                obj = e;
+                assert c != null;
 
-                return false;
+                return c;
             }
 
-            @Override public T reduce() {
-                return obj;
-            }
-        };
+            return new GridSerializableCollection<T>() {
+                @NotNull
+                @Override public Iterator<T> iterator() {
+                    return new GridSerializableIterator<T>() {
+                        private Iterator<T> it1 = c1.iterator();
+                        private Iterator<T> it2 = c2.iterator();
+
+                        @Override public boolean hasNext() {
+                            if (it1 != null)
+                                if (!it1.hasNext())
+                                    it1 = null;
+                                else
+                                    return true;
+
+                            return it2.hasNext();
+                        }
+
+                        @Override public T next() {
+                            return it1 != null ? it1.next() : it2.next();
+                        }
+
+                        @Override public void remove() {
+                            throw new UnsupportedOperationException();
+                        }
+                    };
+                }
+
+                @Override public boolean contains(Object o) {
+                    return c1.contains(o) || c2.contains(o);
+                }
+
+                @Override public int size() {
+                    return c1.size() + c2.size();
+                }
+
+                @Override public boolean equals(Object obj) {
+                    return obj instanceof Collection && eqNotOrdered(this, (Collection<?>)obj);
+                }
+            };
+        }
     }
 
     /**
-     * Gets reducer which always returns {@code true} from {@link org.apache.ignite.lang.IgniteReducer#collect(Object)}
-     * method and passed in {@code element} from {@link org.apache.ignite.lang.IgniteReducer#reduce()} method.
+     * Concatenates an elements to an array.
      *
-     * @param elem Element to return from {@link org.apache.ignite.lang.IgniteReducer#reduce()} method.
-     * @param <T> Reducer element type.
-     * @param <R> Return element type.
-     * @return Passed in element.
+     * @param arr Array.
+     * @param obj One or more elements.
+     * @return Concatenated array.
      */
-    public static <T, R> IgniteReducer<T, R> continuousReducer(final R elem) {
-        return new R1<T, R>() {
-            @Override public boolean collect(T e) {
-                return true;
-            }
+    public static <T> T[] concat(@Nullable T[] arr, T... obj) {
+        T[] newArr;
 
-            @Override public R reduce() {
-                return elem;
-            }
-        };
+        if (arr == null || arr.length == 0)
+            newArr = obj;
+        else {
+            newArr = Arrays.copyOf(arr, arr.length + obj.length);
+
+            System.arraycopy(obj, 0, newArr, arr.length, obj.length);
+        }
+
+        return newArr;
     }
 
     /**
-     * Gets reducer which always returns {@code true} from {@link org.apache.ignite.lang.IgniteReducer#collect(Object)}
-     * method and passed in {@code element} from {@link org.apache.ignite.lang.IgniteReducer#reduce()} method.
+     * Concatenates multiple iterators as single one.
      *
-     * @param elem Element to return from {@link org.apache.ignite.lang.IgniteReducer#reduce()} method.
-     * @param <T> Reducer element type.
-     * @return Passed in element.
+     * @param iters Iterators.
+     * @return Single iterator.
      */
-    public static <T> IgniteReducer<T, T> identityReducer(final T elem) {
-        return new R1<T, T>() {
-            @Override public boolean collect(T e) {
-                return true;
-            }
+    @SuppressWarnings("unchecked")
+    public static <T> Iterator<T> concat(Iterator<T> ... iters) {
+        if (iters.length == 1)
+            return iters[0];
 
-            @Override public T reduce() {
-                return elem;
-            }
-        };
+        return concat(asList(iters).iterator());
     }
 
     /**
-     * Gets reducer closure that calculates harmonic mean.
-     * <p>
-     * <img src="{@docRoot}/img/havg.png">
+     * Concatenates multiple iterators as single one.
      *
-     * @return Reducer closure that calculated harmonic mean.
+     * @param iters Iterator over iterators.
+     * @return Single iterator.
      */
-    public static <T extends Number> IgniteReducer<T, Double> havgReducer() {
-        return new R1<T, Double>() {
-            private double sum;
-            private int i;
+    @SuppressWarnings("unchecked")
+    public static <T> Iterator<T> concat(final Iterator<Iterator<T>> iters) {
+        if (!iters.hasNext())
+            return Collections.<T>emptySet().iterator();
 
-            private final Object lock = new Object();
+        return new Iterator<T>() {
+            private Iterator<T> it = iters.next();
 
-            @Override public boolean collect(T e) {
-                if (e != null)
-                    synchronized (lock) {
-                        sum += 1 / e.doubleValue();
+            private Iterator<T> last;
 
-                        i++;
-                    }
+            private T next;
 
-                return true;
+            {
+                advance();
             }
 
-            @Override public Double reduce() {
-                synchronized (lock) {
-                    return i / sum;
-                }
-            }
-        };
-    }
+            private void advance() {
+                for (;;) {
+                    if (it.hasNext()) {
+                        next = it.next();
 
-    /**
-     * Gets reducer closure that calculates sum of integer elements.
-     * <p>
-     * <img src="{@docRoot}/img/sum.png">
-     *
-     * @return Reducer that calculates sum of integer elements.
-     */
-    public static IgniteReducer<Integer, Integer> sumIntReducer() {
-        return new R1<Integer, Integer>() {
-            private AtomicInteger sum = new AtomicInteger(0);
+                        assert next != null;
 
-            @Override public boolean collect(Integer e) {
-                if (e != null)
-                    sum.addAndGet(e);
+                        return;
+                    }
 
-                return true;
-            }
+                    if (!iters.hasNext())
+                        return;
 
-            @Override public Integer reduce() {
-                return sum.get();
+                    it = iters.next();
+                }
             }
-        };
-    }
-
-    /**
-     * Gets reducer closure that calculates sum of long integer elements.
-     * <p>
-     * <img src="{@docRoot}/img/sum.png">
-     *
-     * @return Reducer that calculates sum of long integer elements.
-     */
-    public static IgniteReducer<Long, Long> sumLongReducer() {
-        return new R1<Long, Long>() {
-            private AtomicLong sum = new AtomicLong(0);
 
-            @Override public boolean collect(Long e) {
-                if (e != null)
-                    sum.addAndGet(e);
-
-                return true;
+            @Override public boolean hasNext() {
+                return next != null;
             }
 
-            @Override public Long reduce() {
-                return sum.get();
-            }
-        };
-    }
+            @Override public T next() {
+                T res = next;
 
-    /**
-     * Gets reducer closure that calculates sum of all elements.
-     * <p>
-     * <img src="{@docRoot}/img/sum.png">
-     *
-     * @return Reducer that calculates sum of all elements.
-     */
-    @SuppressWarnings("unchecked")
-    public static IgniteReducer<Double, Double> sumDoubleReducer() {
-        return new R1<Double, Double>() {
-            private double sum;
+                if (res == null)
+                    throw new NoSuchElementException();
 
-            private final Object lock = new Object();
+                next = null;
 
-            @Override public boolean collect(Double e) {
-                if (e != null)
-                    synchronized (lock) {
-                        sum += e;
-                    }
+                last = it;
 
-                return true;
+                advance();
+
+                return res;
             }
 
-            @Override public Double reduce() {
-                synchronized (lock) {
-                    return sum;
-                }
+            @Override public void remove() {
+                if (last == null)
+                    throw new IllegalStateException();
+
+                last.remove();
             }
         };
     }
 
     /**
-     * Creates a range list containing numbers in given range.
+     * Loses all elements in input collection that are contained in {@code filter} collection.
      *
-     * @param fromIncl Inclusive start of the range.
-     * @param toExcl Exclusive stop of the range.
-     * @return List containing numbers in range.
+     * @param c Input collection.
+     * @param cp If {@code true} method creates new collection not modifying input,
+     *      otherwise does <tt>in-place</tt> modifications.
+     * @param filter Filter collection. If {@code filter} collection is empty or
+     *      {@code null} - no elements are lost.
+     * @param <T> Type of collections.
+     * @return Collection of remaining elements
      */
-    public static List<Integer> range(int fromIncl, int toExcl) {
-        A.ensure(fromIncl >= 0, "fromIncl >= 0");
-        A.ensure(toExcl >= 0, "toExcl >= 0");
-        A.ensure(toExcl >= fromIncl, "toExcl > fromIncl");
-
-        if (toExcl == fromIncl)
-            return Collections.emptyList();
-
-        List<Integer> list = new ArrayList<>(toExcl - fromIncl);
-
-        for (int i = fromIncl; i < toExcl; i++)
-            list.add(i);
+    public static <T0, T extends T0> Collection<T> lose(Collection<T> c, boolean cp,
+        @Nullable Collection<T0> filter) {
+        A.notNull(c, "c");
 
-        return list;
+        return lose(c, cp, F0.in(filter));
     }
 
     /**
-     * Gets reducer closure that calculates sum of all elements.
-     * <p>
-     * <img src="{@docRoot}/img/sum.png">
+     * Loses all elements in input collection that are evaluated to {@code true} by
+     * all given predicates.
      *
-     * @return Reducer that calculates sum of all elements.
+     * @param c Input collection.
+     * @param cp If {@code true} method creates new collection without modifying the input one,
+     *      otherwise does <tt>in-place</tt> modifications.
+     * @param p Predicates to filter by. If no predicates provided - no elements are lost.
+     * @param <T> Type of collections.
+     * @return Collection of remaining elements.
      */
-    @SuppressWarnings("unchecked")
-    public static IgniteReducer<BigDecimal, BigDecimal> sumBigDecimalReducer() {
-        return new R1<BigDecimal, BigDecimal>() {
-            private BigDecimal sum = BigDecimal.ZERO;
+    public static <T> Collection<T> lose(Collection<T> c, boolean cp, @Nullable IgnitePredicate<? super T>... p) {
+        A.notNull(c, "c");
 
-            private final Object lock = new Object();
+        Collection<T> res;
 
-            @Override public boolean collect(BigDecimal e) {
-                if (e != null)
-                    synchronized (lock) {
-                        sum = sum.add(e);
-                    }
+        if (!cp) {
+            res = c;
 
-                return true;
-            }
+            if (isEmpty(p))
+                res.clear();
+            else if (!isAlwaysFalse(p))
+                for (Iterator<T> iter = res.iterator(); iter.hasNext();)
+                    if (isAll(iter.next(), p))
+                        iter.remove();
+        }
+        else {
+            res = new LinkedList<>();
 
-            @Override public BigDecimal reduce() {
-                synchronized (lock) {
-                    return sum;
-                }
-            }
-        };
+            if (!isEmpty(p) && !isAlwaysTrue(p))
+                for (T t : c)
+                    if (!isAll(t, p))
+                        res.add(t);
+        }
+
+        return res;
     }
 
     /**
-     * Gets reducer closure that calculates sum of all elements.
-     * <p>
-     * <img src="{@docRoot}/img/sum.png">
+     * Loses all entries in input map that are evaluated to {@code true} by all given predicates.
      *
-     * @return Reducer that calculates sum of all elements.
+     * @param m Map to filter.
+     * @param cp If {@code true} method creates new map not modifying input, otherwise does
+     *      <tt>in-place</tt> modifications.
+     * @param p Optional set of predicates to use for filtration. If none provided - original map
+     *  will (or its copy) be returned.
+     * @param <K> Type of the free variable for the predicate and type of map's keys.
+     * @param <V> Type of the free variable for the predicate and type of map's values.
+     * @return Filtered map.
      */
-    @SuppressWarnings("unchecked")
-    public static IgniteReducer<BigInteger, BigInteger> sumBigIntegerReducer() {
-        return new R1<BigInteger, BigInteger>() {
-            private BigInteger sum = BigInteger.ZERO;
+    @SuppressWarnings({"unchecked"})
+    public static <K, V> Map<K, V> lose(Map<K, V> m, boolean cp,
+        @Nullable IgnitePredicate<? super Map.Entry<K, V>>... p) {
+        A.notNull(m, "m");
 
-            private final Object lock = new Object();
+        Map<K, V> res;
 
-            @Override public boolean collect(BigInteger e) {
-                if (e != null)
-                    synchronized (lock) {
-                        sum = sum.add(e);
-                    }
+        if (!cp) {
+            res = m;
 
-                return true;
-            }
+            if (isEmpty(p))
+                res.clear();
+            else if (!isAlwaysFalse(p))
+                for (Iterator<Map.Entry<K, V>> iter = m.entrySet().iterator(); iter.hasNext();)
+                    if (isAll(iter.next(), p))
+                        iter.remove();
+        }
+        else {
+            res = U.newHashMap(m.size());
 
-            @Override public BigInteger reduce() {
-                synchronized (lock) {
-                    return sum;
-                }
-            }
-        };
+            if (!isEmpty(p) && !isAlwaysTrue(p))
+                for (Map.Entry<K, V> e : m.entrySet())
+                    if (!F.isAll(e, p))
+                        res.put(e.getKey(), e.getValue());
+        }
+
+        return res;
     }
 
     /**
-     * Gets reducer closure that concatenates strings using provided delimiter.
+     * Loses all entries in input map which keys are evaluated to {@code true} by all
+     * given predicates.
      *
-     * @param delim Delimiter (optional).
-     * @return Reducer that concatenates strings using provided delimeter.
+     * @param m Map to filter.
+     * @param cp If {@code true} method creates new map not modifying input, otherwise does
+     *      <tt>in-place</tt> modifications.
+     * @param p Optional set of predicates to use for filtration. If none provided - original
+     *      map (or its copy) will be returned.
+     * @param <K> Type of the free variable for the predicate and type of map's keys.
+     * @param <V> Type of map's values.
+     * @return Filtered map.
      */
-    public static IgniteReducer<String, String> concatReducer(@Nullable final String delim) {
-        return new R1<String, String>() {
-            private SB sb = new SB();
-
-            private boolean first = true;
-
-            private final Object lock = new Object();
-
-            @Override public boolean collect(String s) {
-                synchronized (lock) {
-                    if (!first && !isEmpty(delim))
-                        sb.a(delim);
-
-                    sb.a(s);
-
-                    first = false;
-                }
-
-                return true;
-            }
-
-            @Override public String reduce() {
-                synchronized (lock) {
-                    return sb.toString();
-                }
+    public static <K, V> Map<K, V> loseKeys(
+        Map<K, V> m,
+        boolean cp,
+        @Nullable final IgnitePredicate<? super K>... p
+    ) {
+        return lose(m, cp, new P1<Map.Entry<K, V>>() {
+            @Override public boolean apply(Map.Entry<K, V> e) {
+                return isAll(e.getKey(), p);
             }
-        };
+        });
     }
 
     /**
-     * Concatenates strings using provided delimiter.
+     * Loses all entries in input map which values are evaluated to {@code true} by all
+     * given predicates.
      *
-     * @param c Input collection.
-     * @param delim Delimiter (optional).
-     * @return Concatenated string.
+     * @param m Map to filter.
+     * @param cp If {@code true} method creates new map not modifying input, otherwise does
+     *      <tt>in-place</tt> modifications.
+     * @param p Optional set of predicates to use for filtration. If none provided - original
+     *      map (or its copy) will be returned.
+     * @param <K> Type of the free variable for the predicate and type of map's keys.
+     * @param <V> Type of map's values.
+     * @return Filtered map.
      */
-    public static String concat(Iterable<String> c, @Nullable String delim) {
-        A.notNull(c, "c");
-
-        return reduce(c, concatReducer(delim));
+    public static <K, V> Map<K, V> loseValues(Map<K, V> m, boolean cp,
+        @Nullable final IgnitePredicate<? super V>... p) {
+        return lose(m, cp, new P1<Map.Entry<K, V>>() {
+            @Override public boolean apply(Map.Entry<K, V> e) {
+                return isAll(e.getValue(), p);
+            }
+        });
     }
 
     /**
-     * Gets collections of data items from grid job res casted to specified type.
-     * <p>
-     * Here's the typical example of how this method is used in {@code reduce()} method
-     * implementation (this example sums up all the values of {@code Integer} type):
-     * <pre name="code" class="java">
-     * public Integer reduce(List&lt;GridComputeJobResult&gt; res) throws IgniteCheckedException {
-     *     return F.sum(F.&lt;Integer&gt;jobResults(res));
-     * }
-     * </pre>
-     * <p>
-     * Note that this method doesn't create a new collection but simply iterates over the input one.
+     * Loses all elements in input list that are contained in {@code filter} collection.
      *
-     * @param res Collection of grid job res.
-     * @param <T> Type of the data item to cast to. See {@link org.apache.ignite.compute.ComputeJobResult#getData()} method.
-     * @return Collections of data items casted to type {@code T}.
-     * @see org.apache.ignite.compute.ComputeJobResult#getData()
+     * @param c Input list.
+     * @param cp If {@code true} method creates new list not modifying input,
+     *      otherwise does <tt>in-place</tt> modifications.
+     * @param filter Filter collection. If {@code filter} collection is empty or
+     *      {@code null} - no elements are lost.
+     * @param <T> Type of list.
+     * @return List of remaining elements
      */
-    public static <T> Collection<T> jobResults(@Nullable Collection<? extends ComputeJobResult> res) {
-        if (isEmpty(res))
-            return Collections.emptyList();
+    public static <T> List<T> loseList(List<T> c, boolean cp, @Nullable Collection<? super T> filter) {
+        A.notNull(c, "c");
 
-        assert res != null;
+        List<T> res;
 
-        Collection<T> c = new ArrayList<>(res.size());
+        if (!cp) {
+            res = c;
 
-        for (ComputeJobResult r : res)
-            c.add(r.<T>getData());
+            if (filter != null)
+                res.removeAll(filter);
+        }
+        else {
+            res = new LinkedList<>();
 
-        return c;
+            for (T t : c) {
+                if (filter == null || !filter.contains(t))
+                    res.add(t);
+            }
+        }
+
+        return res;
     }
 
     /**
-     * Convenient utility method that returns collection of node IDs for a given
-     * collection of grid nodes.
-     * <p>
-     * Note that this method doesn't create a new collection but simply iterates
-     * over the input one.
+     * Loses all elements in input list for which any of the predicates evaluate to {@code true}.
      *
-     * @param nodes Collection of grid nodes.
-     * @return Collection of node IDs for given collection of grid nodes.
+     * @param c Input list.
+     * @param cp If {@code true} method creates new list not modifying input,
+     *      otherwise does <tt>in-place</tt> modifications.
+     * @param p Looses all elements for which any of the predicates evaluate to {@code true}.
+     * @param <T> Type of list.
+     * @return List of remaining elements
      */
-    public static Collection<UUID> nodeIds(@Nullable Collection<? extends ClusterNode> nodes) {
-        if (nodes == null || nodes.isEmpty())
-            return Collections.emptyList();
+    public static <T> List<T> filterList(List<T> c, boolean cp, @Nullable IgnitePredicate<T>... p) {
+        A.notNull(c, "c");
 
-        return F.viewReadOnly(nodes, node2id());
-    }
+        List<T> res;
 
-    /**
-     * Convenient utility method that returns collection of node ID8s for a given
-     * collection of grid nodes. ID8 is a shorter string representation of node ID,
-     * mainly the first 8 characters.
-     * <p>
-     * Note that this method doesn't create a new collection but simply iterates
-     * over the input one.
-     *
-     * @param nodes Collection of grid nodes.
-     * @return Collection of node IDs for given collection of grid nodes.
-     */
-    public static Collection<String> nodeId8s(@Nullable Collection<? extends ClusterNode> nodes) {
-        if (nodes == null || nodes.isEmpty())
-            return Collections.emptyList();
+        if (!cp) {
+            res = c;
 
-        return F.viewReadOnly(nodes, node2id8());
-    }
+            if (p != null)
+                for (Iterator<T> it = c.iterator(); it.hasNext();)
+                    if (isAny(it.next(), p))
+                        it.remove();
+        }
+        else {
+            res = new ArrayList<>(c.size());
 
-    /**
-     * Convenient utility method that returns collection of node ID8s for a given
-     * collection of node IDs. ID8 is a shorter string representation of node ID,
-     * mainly the first 8 characters.
-     * <p>
-     * Note that this method doesn't create a new collection but simply iterates
-     * over the input one.
-     *
-     * @param ids Collection of nodeIds.
-     * @return Collection of node IDs for given collection of grid nodes.
-     */
-    public static Collection<String> id8s(@Nullable Collection<UUID> ids) {
-        if (ids == null || ids.isEmpty())
-            return Collections.emptyList();
+            for (T t : c)
+                if (!isAny(t, p))
+                    res.add(t);
+        }
 
-        return F.viewReadOnly(ids, id2id8());
+        return res;
     }
 
     /**
-     * Convenient utility method that returns collection of node attributes for a given
-     * collection of grid nodes.
-     * <p>
-     * Note that this method doesn't create a new collection but simply iterates over the input one.
+     * Gets closure which converts node to node ID.
      *
-     * @param nodes Collection of grid nodes.
-     * @param attr Name of the attribute to return from each node.
-     * @param <T> Type of the attribute.
-     * @return Collection of node attributes for given collection of grid nodes.
+     * @return Closure which converts node to node ID.
      */
-    public static <T> Collection<T> nodeAttributes(Collection<? extends ClusterNode> nodes, String attr) {
-        A.notNull(nodes, "nodes", attr, "attr");
-
-        Collection<T> c = new ArrayList<>(nodes.size());
-
-        for (ClusterNode n : nodes)
-            c.add(n.<T>attribute(attr));
-
-        return c;
+    public static IgniteClosure<ClusterNode, UUID> node2id() {
+        return NODE2ID;
     }
 
     /**
-     * Gets closure that calls {@code System.out.println()} on its bound variable.
+     * Creates grid node predicate evaluating on the given node ID.
      *
-     * @param <T> Type of the bound variable.
-     * @return Closure that calls {@code System.out.println()} on its bound variable.
+     * @param nodeId Node ID for which returning predicate will evaluate to {@code true}.
+     * @return Grid node predicate evaluating on the given node ID.
+     * @see #idForNodeId(UUID)
+     * @see #nodeIds(Collection)
      */
-    @SuppressWarnings("unchecked")
-    public static <T> IgniteInClosure<T> println() {
-        return (IgniteInClosure<T>)PRINTLN;
-    }
+    public static <T extends ClusterNode> IgnitePredicate<T> nodeForNodeId(final UUID nodeId) {
+        A.notNull(nodeId, "nodeId");
 
-    /**
-     * Creates absolute closure that does <tt>System.out.println(msg)</tt>.
-     *
-     * @param msg Message to print.
-     * @return Absolute closure that print message.
-     */
-    public static GridAbsClosure println(final String msg) {
-        return new CA() {
-            @Override public void apply() {
-                System.out.println(msg);
+        return new P1<T>() {
+            @Override public boolean apply(ClusterNode e) {
+                return e.id().equals(nodeId);
             }
         };
     }
 
     /**
-     * Creates absolute closure that does <tt>System.out.print(msg)</tt>.
+     * Creates grid node predicate evaluating on the given node IDs.
      *
-     * @param msg Message to print.
-     * @return Absolute closure that print message.
+     * @param nodeIds Collection of node IDs.
+     * @return Grid node predicate evaluating on the given node IDs.
+     * @see #idForNodeId(UUID)
+     * @see #nodeIds(Collection)
      */
-    public static GridAbsClosure print(final String msg) {
-        return new CA() {
-            @Override public void apply() {
-                System.out.print(msg);
-            }
-        };
-    }
+    public static <T extends ClusterNode> IgnitePredicate<T> nodeForNodeIds(@Nullable final Collection<UUID>
+        nodeIds) {
+        if (isEmpty(nodeIds))
+            return alwaysFalse();
 
-    /**
-     * Gets closure that prints out its bound variable.
-     *
-     * @param pre String value to print before each variable.
-     * @param post String value to print after each variable.
-     * @param <T> Type of the bound variable.
-     * @return Closure that calls {@code System.out.print(pre); System.out.print(t); System.out.println(post)}
-     *      on its bound variable.
-     */
-    public static <T> IgniteInClosure<T> println(@Nullable final String pre, @Nullable final String post) {
-        return new CI1<T>() {
-            @Override public void apply(T t) {
-                String sPre = pre == null ? "" : pre;
-                String sPost = post == null ? "" : post;
+        assert nodeIds != null;
 
-                System.out.println(sPre + t + sPost);
+        return new P1<T>() {
+            @Override public boolean apply(ClusterNode e) {
+                return nodeIds.contains(e.id());
             }
         };
     }
 
     /**
-     * Gets closure that prints out its bound variable.
+     * Creates {@link UUID} predicate evaluating on the given node ID.
      *
-     * @param fmt Format string as for {@link PrintStream#printf(String, Object...)} method.
-     * @param <T> Type of the bound variable.
-     * @return Closure that prints out its bound variable.
+     * @param nodeId Node ID for which returning predicate will evaluate to {@code true}.
+     * @return {@link UUID} predicate evaluating on the given node ID.
+     * @see #nodeForNodeId(UUID)
+     * @see #nodeIds(Collection)
      */
-    public static <T> IgniteInClosure<T> printf(final String fmt) {
-        return new CI1<T>() {
-            @Override public void apply(T t) {
-                System.out.printf(fmt, t);
+    public static IgnitePredicate<UUID> idForNodeId(final UUID nodeId) {
+        A.notNull(nodeId, "nodeId");
+
+        return new P1<UUID>() {
+            @Override public boolean apply(UUID id) {
+                return id.equals(nodeId);
             }
         };
     }
 
     /**
-     * Gets closure that prints out its bound variable
+     * Creates predicates that evaluates to {@code true} for each node in given collection.
+     * Note that if collection is empty the result predicate will always evaluate to {@code false}.
+     * Implementation simply creates {@link GridNodePredicate} instance.
      *
-     * @return Closure that prints out its bound variable.
+     * @param nodes Collection of nodes. If none provided - result predicate will always
+     *      return {@code false}.
+     * @return Predicates that evaluates to {@code true} for each node in given collection.
      */
-    @SuppressWarnings("unchecked")
-    public static <T> IgniteInClosure<T> print() {
-        return (IgniteInClosure<T>)PRINT;
+    public static IgnitePredicate<ClusterNode> nodeForNodes(ClusterNode... nodes) {
+        return new GridNodePredicate(nodes);
     }
 
     /**
-     * Gets closure that prints out its bound variable.
+     * Retains all elements in input collection that are contained in {@code filter}.
      *
-     * @param pre String value to print before each variable.
-     * @param post String value to print after each variable.
-     * @return Closure that prints out its bound variable.
+     * @param c Input collection.
+     * @param cp If {@code true} method creates collection not modifying input, otherwise does
+     *      <tt>in-place</tt> modifications.
+     * @param filter Filter collection. If filter collection is {@code null} or empty -
+     *      an empty collection will be returned.
+     * @param <T> Type of collections.
+     * @return Collection of retain elements.
      */
-    public static <T> IgniteInClosure<T> print(@Nullable final String pre, @Nullable final String post) {
-        return new CI1<T>() {
-            @Override public void apply(T t) {
-                String sPre = pre == null ? "" : pre;
-                String sPost = post == null ? "" : post;
+    public static <T0, T extends T0> Collection<T> retain(Collection<T> c, boolean cp,
+        @Nullable Collection<? extends T0> filter) {
+        A.notNull(c, "c");
 
-                System.out.print(sPre + t + sPost);
-            }
-        };
+        return retain(c, cp, F0.in(filter));
     }
 
     /**
-     * Gets random value from given collection.
+     * Retains all elements in input collection that are evaluated to {@code true}
+     * by all given predicates.
      *
-     * @param c Input collection (no {@code null} and not emtpy).
-     * @param <T> Type of the collection.
-     * @return Random value from the input collection.
+     * @param c Input collection.
+     * @param cp If {@code true} method creates collection not modifying input, otherwise does
+     *      <tt>in-place</tt> modifications.
+     * @param p Predicates to filter by. If no predicates provides - all elements
+     *      will be retained.
+     * @param <T> Type of collections.
+     * @return Collection of retain elements.
      */
-    @SuppressWarnings("UnusedDeclaration")
-    public static <T> T rand(Collection<? extends T> c) {
+    public static <T> Collection<T> retain(Collection<T> c, boolean cp, @Nullable IgnitePredicate<? super T>... p) {
         A.notNull(c, "c");
 
-        int n = ThreadLocalRandom8.current().nextInt(c.size());
-
-        int i = 0;
-
-        for (T t : c) {
-            if (i++ == n)
-                return t;
-        }
-
-        throw new ConcurrentModificationException();
+        return lose(c, cp, not(p));
     }
 
     /**
-     * Gets random value from given collection which may be modified concurrently.
+     * Retains only up to first {@code num} elements in the input collection.
      *
      * @param c Input collection.
-     * @param <T> Type of the collection.
-     * @return Random value from the input collection.
+     * @param cp If {@code true} method creates collection not modifying input, otherwise does
+     *      <tt>in-place</tt> modifications.
+     * @param num Maximum number of elements to retain (the actual number can be
+     *      less if the input collection contains less elements).
+     * @param <T> Type of the collections.
+     * @return Collection contains up to {@code num} first elements from the input collection.
      */
-    @Nullable public static <T> T randConcurrent(Collection<? extends T> c) {
+    public static <T> Collection<T> retain(Collection<T> c, boolean cp, int num) {
         A.notNull(c, "c");
+        A.ensure(num >= 0, "num >= 0");
 
-        int size = c.size();
+        Collection<T> res;
 
-        if (size == 0)
-            return null;
+        if (!cp) {
+            res = c;
 
-        int n = ThreadLocalRandom8.current().nextInt(size);
+            if (num < res.size()) {
+                int i = 0;
 
-        int i = 0;
+                for (Iterator<T> iter = res.iterator(); iter.hasNext();) {
+                    iter.next();
 
-        T res = null;
+                    if (i++ >= num)
+                        iter.remove();
+                }
+            }
+        }
+        else {
+            res = new ArrayList<>(num);
 
-        for (T t : c) {
-            if (i++ == n)
-                return t;
+            Iterator<? extends T> iter = c.iterator();
 
-            res = t;
+            for (int i = 0; i < num && iter.hasNext(); i++)
+                res.add(iter.next());
         }
 
         return res;
     }
 
     /**
-     * Gets random value from given list. For random-access lists this
-     * operation is O(1), otherwise O(n).
+     * Curries given closure.
      *
-     * @param l Input collection.
-     * @param <T> Type of the list elements.
-     * @return Random value from the input list.
+     * @param f Closure.
+     * @param e Parameter.
+     * @param <T> Input type.
+     * @param <R> Output type.
+     * @return Curried closure.
      */
-    public static <T> T rand(List<T> l) {
-        A.notNull(l, "l");
-
-        return l.get(ThreadLocalRandom8.current().nextInt(l.size()));
+    public static <T, R> IgniteOutClosure<R> curry(final IgniteClosure<? super T, R> f, final T e) {
+        return new IgniteOutClosure<R>() {
+            @Override public R apply() {
+                return f.apply(e);
+            }
+        };
     }
 
     /**
-     * Gets random value from given array. This operation
-     * does not iterate through array elements and returns immediately.
+     * Curries given closure.
      *
-     * @param c Input collection.
-     * @param <T> Type of the collection.
-     * @return Random value from the input collection.
+     * @param f Closure.
+     * @param e Parameter.
+     * @param <T> Input type.
+     * @return Curried closure.
      */
-    public static <T> T rand(T... c) {
-        A.notNull(c, "c");
-
-        return c[ThreadLocalRandom8.current().nextInt(c.length)];
+    public static <T> GridAbsClosure curry(final IgniteInClosure<? super T> f, final T e) {
+        return new GridAbsClosure() {
+            @Override public void apply() {
+                f.apply(e);
+            }
+        };
     }
 
     /**
-     * Concatenates an element to a collection. If {@code copy} flag is {@code true}, then
-     * a new collection will be created and the element and passed in collection will be
-     * copied into the new one. The returned collection will be modifiable. If {@code copy}
-     * flag is {@code false}, then a read-only view will be created over the element and given
-     * collections and no copying will happen.
+     * Converts array to {@link List}. Note that resulting list cannot
+     * be altered in size, as it it based on the passed in array -
+     * only current elements can be changed.
+     * <p>
+     * Note that unlike {@link Arrays#asList(Object[])}, this method is
+     * {@code null}-safe. If {@code null} is passed in, then empty list
+     * will be returned.
      *
-     * @param cp Copy flag.
-     * @param t First element.
-     * @param c Second collection.
-     * @param <T> Element type.
-     * @return Concatenated collection.
+     * @param vals Array of values
+     * @param <T> Array type.
+     * @return {@link List} instance for array.
      */
-    public static <T> Collection<T> concat(boolean cp, @Nullable final T t, @Nullable final Collection<T> c) {
-        if (cp) {
-            if (isEmpty(c)) {
-                Collection<T> l = new ArrayList<>(1);
+    public static <T> List<T> asList(@Nullable T... vals) {
+        return isEmpty(vals) ? Collections.<T>emptyList() : Arrays.asList(vals);
+    }
 
-                l.add(t);
+    /**
+     * Creates new empty iterator.
+     *
+     * @param <T> Type of the iterator.
+     * @return Newly created empty iterator.
+     */
+    public static <T> GridIterator<T> emptyIterator() {
+        return new GridEmptyIterator<>();
+    }
 
-                return l;
+    /**
+     * Flattens collection-of-collections and returns collection over the
+     * elements of the inner collections. This method doesn't create any
+     * new collections or copies any elements.
+     * <p>
+     * Note that due to non-copying nature of implementation, the
+     * {@link Collection#size() size()} method of resulting collection will have to
+     * iterate over all elements to produce size. Method {@link Collection#isEmpty() isEmpty()},
+     * however, is constant time and is much more preferable to use instead
+     * of {@code 'size()'} method when checking if list is not empty.
+     *
+     * @param c Input collection of collections.
+     * @param <T> Type of the inner collections.
+     * @return Iterable over the elements of the inner collections.
+     */
+    public static <T> Collection<T> flatCollections(@Nullable final Collection<? extends Collection<T>> c) {
+        if (F.isEmpty(c))
+            return Collections.emptyList();
+
+        return new GridSerializableCollection<T>() {
+            @NotNull
+            @Override public Iterator<T> iterator() {
+                return flat((Iterable<? extends Iterable<T>>)c);
             }
 
-            assert c != null;
+            @Override public int size() {
+                return F.size(iterator());
+            }
 
-            Collection<T> ret = new ArrayList<>(c.size() + 1);
+            @Override public boolean isEmpty() {
+                return !iterator().hasNext();
+            }
+        };
+    }
 
-            ret.add(t);
-            ret.addAll(c);
+    /**
+     * Flattens iterable-of-iterables and returns iterable over the
+     * elements of the inner collections. This method doesn't create any
+     * new collections or copies any elements.
+     *
+     * @param c Input collection of collections.
+     * @param <T> Type of the inner collections.
+     * @return Iterable over the elements of the inner collections.
+     */
+    public static <T> GridIterator<T> flat(@Nullable final Iterable<? extends Iterable<T>> c) {
+        return isEmpty(c) ? GridFunc.<T>emptyIterator() : new GridIteratorAdapter<T>() {
+            /** */
+            private Iterator<? extends Iterable<T>> a = c.iterator();
 
-            return ret;
-        }
-        else {
-            if (isEmpty(c))
-                return Collections.singletonList(t);
+            /** */
+            private Iterator<T> b;
 
-            assert c != null;
+            /** */
+            private boolean moved = true;
 
-            return new GridSerializableCollection<T>() {
-                @NotNull
-                @Override public Iterator<T> iterator() {
-                    return new GridSerializableIterator<T>() {
-                        private Iterator<T> it;
+            /** */
+            private boolean more;
 
-                        @Override public boolean hasNext() {
-                            return it == null || it.hasNext();
-                        }
+            @Override public boolean hasNextX() {
+                if (!moved)
+                    return more;
 
-                        @Nullable @Override public T next() {
-                            if (it == null) {
-                                it = c.iterator();
+                moved = false;
 
-                                return t;
-                            }
+                if (b != null && b.hasNext())
+                    return more = true;
 
-                            return it.next();
-                        }
+                while (a.hasNext()) {
+                    b = a.next().iterator();
 
-                        @Override public void remove() {
-                            throw new UnsupportedOperationException();
-                        }
-                    };
+                    if (b.hasNext())
+                        return more = true;
                 }
 
-                @Override public int size() {
-                    return c.size() + 1;
-                }
+                return more = false;
+            }
 
-                @Override public boolean equals(Object obj) {
-                    return obj instanceof Collection && eqNotOrdered(this, (Collection)obj);
+            @Override public T nextX() {
+                if (hasNext()) {
+                    moved = true;
+
+                    return b.next();
                 }
-            };
-        }
+
+                throw new NoSuchElementException();
+            }
+
+            @Override public void removeX() {
+                assert b != null;
+
+                b.remove();
+            }
+        };
     }
 
     /**
-     * Concatenates 2 collections into one. If {@code copy} flag is {@code true}, then
-     * a new collection will be created and these collections will be copied into the
-     * new one. The returned collection will be modifiable. If {@code copy} flag is
-     * {@code false}, then a read-only view will be created over given collections
-     * and no copying will happen.
+     * Flattens iterable-of-iterators and returns iterator over the
+     * elements of the inner collections. This method doesn't create any
+     * new collections or copies any elements.
      *
-     * @param cp Copy flag.
-     * @param c1 First collection.
-     * @param c2 Second collection.
-     * @param <T> Element type.
-     * @return Concatenated {@code non-null} collection.
+     * @param c Input iterable of iterators.
+     * @return Iterator over the elements of given iterators.
      */
-    public static <T> Collection<T> concat(boolean cp, @Nullable final Collection<T> c1,
-        @Nullable final Collection<T> c2) {
-        if (cp) {
-            if (isEmpty(c1) && isEmpty(c2))
-                return new ArrayList<>(0);
+    public static <T> Iterator<T> flatIterators(@Nullable final Iterable<Iterator<T>> c) {
+        return isEmpty(c) ? GridFunc.<T>emptyIterator() : new GridIteratorAdapter<T>() {
+            /** */
+            private Iterator<? extends Iterator<T>> a = c.iterator();
 
-            if (isEmpty(c1))
-                return new ArrayList<>(c2);
+            /** */
+            private Iterator<T> b;
 
-            if (isEmpty(c2))
-                return new ArrayList<>(c1);
+            /** */
+            private boolean moved = true;
 
-            assert c1 != null && c2 != null;
+            /** */
+            private boolean more;
 
-            Collection<T> c = new ArrayList<>(c1.size() + c2.size());
+            @Override public boolean hasNextX() {
+                if (!moved)
+                    return more;
 
-            c.addAll(c1);
-            c.addAll(c2);
+                moved = false;
 
-            return c;
-        }
-        else {
-            if (isEmpty(c1) && isEmpty(c2))
-                return Collections.emptyList();
+                if (b != null && b.hasNext())
+                    return more = true;
 
-            if (isEmpty(c1) || isEmpty(c2)) {
-                Collection<T> c = isEmpty(c1) ? c2 : c1;
+                while (a.hasNext()) {
+                    b = a.next();
 
-                assert c != null;
+                    if (b.hasNext())
+                        return more = true;
+                }
 
-                return c;
+                return more = false;
             }
 
-            assert c1 != null && c2 != null;
-
-            return new GridSerializableCollection<T>() {
-                @NotNull
-                @Override public Iterator<T> iterator() {
-                    return new GridSerializableIterator<T>() {
-                        private Iterator<T> it1 = c1.iterator();
-                        private Iterator<T> it2 = c2.iterator();
-
-                        @Override public boolean hasNext() {
-                            if (it1 != null)
-                                if (!it1.hasNext())
-                                    it1 = null;
-                                else
-                                    return true;
-
-                            return it2.hasNext();
-                        }
-
-                        @Override public T next() {
-                            return it1 != null ? it1.next() : it2.next();
-                        }
+            @Override public T nextX() {
+                if (hasNext()) {
+                    moved = true;
 
-                        @Override public void remove() {
-                            throw new UnsupportedOperationException();
-                        }
-                    };
+                    return b.next();
                 }
 
-                @Override public boolean contains(Object o) {
-                    return c1.contains(o) || c2.contains(o);
-                }
+                throw new NoSuchElementException();
+            }
 
-                @Override public int size() {
-                    return c1.size() + c2.size();
-                }
+            @Override public void removeX() {
+                assert b != null;
 
-                @Override public boolean equals(Object obj) {
-                    return obj instanceof Collection && eqNotOrdered(this, (Collection<?>)obj);
-                }
-            };
-        }
+                b.remove();
+            }
+        };
     }
 
     /**
-     * Concatenates an elements to an array.
+     * Converts given runnable to an absolute closure.
      *
-     * @param arr Array.
-     * @param obj One or more elements.
-     * @return Concatenated array.
+     * @param r Runnable to convert to closure. If {@code null} - no-op closure is returned.
+     * @return Closure that wraps given runnable. Note that wrapping closure always returns {@code null}.
      */
-    public static <T> T[] concat(@Nullable T[] arr, T... obj) {
-        T[] newArr;
-
-        if (arr == null || arr.length == 0)
-            newArr = obj;
-        else {
-            newArr = Arrays.copyOf(arr, arr.length + obj.length);
-
-            System.arraycopy(obj, 0, newArr, arr.length, obj.length);
-        }
-
-        return newArr;
-    }
+    public static GridAbsClosure as(@Nullable final Runnable r) {
+        return new CA() {
+            @Override public void apply() {
+                if (r != null)
+                    r.run();
+            }
+        };
+    }
 
     /**
-     * Concatenates multiple iterators as single one.
+     * Gets size of the given collection with provided optional predicates.
      *
-     * @param iters Iterators.
-     * @return Single iterator.
+     * @param c Collection to size.
+     * @param p Optional predicates that filters out elements from count.
+     * @param <T> Type of the iterator.
+     * @return Number of elements in the collection for which all given predicates
+     *      evaluates to {@code true}. If no predicates is provided - all elements are counted.
      */
-    @SuppressWarnings("unchecked")
-    public static <T> Iterator<T> concat(Iterator<T> ... iters) {
-        if (iters.length == 1)
-            return iters[0];
-
-        return concat(asList(iters).iterator());
+    public static <T> int size(@Nullable Collection<? extends T> c, @Nullable IgnitePredicate<? super T>... p) {
+        return c == null || c.isEmpty() ? 0 : isEmpty(p) || isAlwaysTrue(p) ? c.size() : size(c.iterator(), p);
     }
 
     /**
-     * Concatenates multiple iterators as single one.
+     * Gets size of the given iterator with provided optional predicates. Iterator
+     * will be traversed to get the count.
      *
-     * @param iters Iterator over iterators.
-     * @return Single iterator.
+     * @param it Iterator to size.
+     * @param p Optional predicates that filters out elements from count.
+     * @param <T> Type of the iterator.
+     * @return Number of elements in the iterator for which all given predicates
+     *      evaluates to {@code true}. If no predicates is provided - all elements are counted.
      */
-    @SuppressWarnings("unchecked")
-    public static <T> Iterator<T> concat(final Iterator<Iterator<T>> iters) {
-        if (!iters.hasNext())
-            return Collections.<T>emptySet().iterator();
-
-        return new Iterator<T>() {
-            privat

<TRUNCATED>