ACollectionHelper { public static <T, X, E extends Throwable> Collection<X> flatMap(Iterable<T> coll, AFunction1<? super T, ? extends Iterable<X>, E> f) throws E { final List<X> result = new ArrayList<>(); for(T o: coll) { for(X el: f.apply(o)) { result.add(el); } } return result; }  static Set<T> createSet(Iterator<T> elements); static Set<T> createSet(Iterable<T> elements); static Set<U> createSet(Iterator<T> elements, AFunction1<T,U,E> f); static Set<U> createSet(Iterable<T> elements, AFunction1<T,U,E> f); static String mkString(Iterable<?> iterable); static String mkString(Iterable<?> iterable, String separator); static String mkString(Iterable<?> iterable, String prefix, String separator, String suffix); static AOption<T> find(Iterable<T> coll, APredicate<? super T, E> pred); static boolean forAll(Iterable<T> coll, APredicate<? super T, E> pred); static boolean exists(Iterable<T> coll, APredicate<? super T, E> pred); static Collection<X> map(Iterable<T> coll, AFunction1<? super T, ? extends X, E> f); static List<X> map(List<T> coll, AFunction1<? super T, ? extends X, E> f); static Set<X> map(Set<T> coll, AFunction1<? super T, ? extends X, E> f); static Collection<X> flatMap(Iterable<T> coll, AFunction1<? super T, ? extends Iterable<X>, E> f); static List<X> flatMapList(Iterable<T> coll, AFunction1<? super T, ? extends Iterable<X>, E> f); static Set<X> flatMapSet(Iterable<T> coll, AFunction1<? super T, ? extends Iterable<X>, E> f); static Collection<T> flatten(Iterable<? extends Iterable<T>> coll); static List<T> flattenList(Iterable<? extends Iterable<T>> coll); static Set<T> flattenSet(Iterable<? extends Iterable<T>> coll); static Collection<X> collect(Iterable<T> coll, APartialFunction<? super T, ? extends X, E> pf); static List<X> collect(List<T> coll, APartialFunction<? super T, ? extends X, E> pf); static Set<X> collect(Set<T> coll, APartialFunction<? super T, ? extends X, E> pf); static Collection<T> filter(Iterable<T> coll, APredicate<? super T, E> pred); static List<T> filter(List<T> coll, APredicate<? super T, E> pred); static Set<T> filter(Set<T> coll, APredicate<? super T, E> pred); static Collection<T> filterNot(Iterable<T> coll, APredicate<? super T, E> pred); static List<T> filterNot(List<T> coll, APredicate<? super T, E> pred); static Set<T> filterNot(Set<T> coll, APredicate<? super T, E> pred); static Map<X, Collection<T>> groupBy(Iterable<T> coll, AFunction1<? super T, ? extends X, E> f); static Map<X, List<T>> groupBy(List<T> coll, AFunction1<? super T, ? extends X, E> f); static Map<X, Set<T>> groupBy(Set<T> coll, AFunction1<? super T, ? extends X, E> f); static Map<AEqualsWrapper<X>, Collection<T>> groupBy(Iterable<T> coll, AFunction1<? super T, ? extends X, E> f, AEquality keyEquality); static Map<AEqualsWrapper<X>, List<T>> groupBy(List<T> coll, AFunction1<? super T, ? extends X, E> f, AEquality keyEquality); static Map<AEqualsWrapper<X>, Set<T>> groupBy(Set<T> coll, AFunction1<? super T, ? extends X, E> f, AEquality keyEquality); static R foldLeft(Iterable<T> coll, R startValue, AFunction2<R, ? super T, R, E> f); static R foldRight(List<T> coll, R startValue, AFunction2<R, ? super T, R, E> f); static ACollectionWrapper<T> asACollectionCopy(Collection<T> c); @SuppressWarnings("unchecked") static ACollectionWrapper<T> asACollectionView(Collection<T> c); static ASetWrapper<T> asASetView(Collection<T> c); @SuppressWarnings("unchecked") static AArrayWrapper<T> asArrayCopy(T[] c); static AArrayWrapper<T> asArrayView(T[] c); static List<T> asJavaUtilList(Iterable<T> c); static Collection<T> asJavaUtilCollection(Iterable<T> c); static List<T> asJavaUtilCollection(Iterator<T> c);  }
@Test public void testFlatMapTokens() { final AFunction1NoThrow<String, List<String>> tokens = new AFunction1NoThrow<String, List<String>>() { @Override public List<String> apply(String param) { return Arrays.asList (param.split (" ")); } }; assertEquals(Arrays.<String>asList(), ACollectionHelper.flatMap(Arrays.<String>asList(), tokens)); assertEquals(Arrays.asList("a"), ACollectionHelper.flatMap (Arrays.asList ("a"), tokens)); assertEquals(Arrays.asList("a", "bc", "def"), ACollectionHelper.flatMap (Arrays.asList ("a bc def"), tokens)); assertEquals(Arrays.asList("a", "bc", "def", "x", "yz"), ACollectionHelper.flatMap (Arrays.asList ("a bc def", "x yz"), tokens)); }
@Test public void testFlatMapOption() { final AFunction1NoThrow<String, AOption<String>> uppercaseFirst = new AFunction1NoThrow<String, AOption<String>>() { @Override public AOption<String> apply(String param) { if(Character.isUpperCase(param.charAt(0))) return AOption.some(param.substring(0, 1)); return AOption.none (); } }; assertEquals(Arrays.<String>asList(), ACollectionHelper.flatMap(Arrays.<String>asList(), uppercaseFirst)); assertEquals(Arrays.asList("A"), ACollectionHelper.flatMap(Arrays.asList("Asdf"), uppercaseFirst)); assertEquals(Arrays.asList("A", "Q"), ACollectionHelper.flatMap(Arrays.asList("xyz", "Asdf", "Qzd", "rLS"), uppercaseFirst)); }