/* * Copyright 2015, 2016 Tagir Vetaleev * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package one.util.streamex; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.AbstractList; import java.util.AbstractMap; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NavigableMap; import java.util.Objects; import java.util.Optional; import java.util.Queue; import java.util.Random; import java.util.Set; import java.util.SortedMap; import java.util.Spliterator; import java.util.TreeSet; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import one.util.streamex.IntStreamEx; import one.util.streamex.MoreCollectors; import one.util.streamex.StreamEx; import org.junit.FixMethodOrder; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runners.MethodSorters; import static one.util.streamex.TestHelpers.*; import static org.junit.Assert.*; import static java.util.Arrays.asList; /** * @author Tagir Valeev */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class StreamExTest { @Rule public TemporaryFolder tmp = new TemporaryFolder(); @Test public void testCreate() { assertEquals(asList(), StreamEx.empty().toList()); // double test is intended assertEquals(asList(), StreamEx.empty().toList()); assertEquals(asList("a"), StreamEx.of("a").toList()); assertEquals(asList("a"), StreamEx.of(Optional.of("a")).toList()); assertEquals(asList(), StreamEx.of(Optional.ofNullable(null)).toList()); assertEquals(asList(), StreamEx.ofNullable(null).toList()); assertEquals(asList("a"), StreamEx.ofNullable("a").toList()); assertEquals(asList((String) null), StreamEx.of((String) null).toList()); assertEquals(asList("a", "b"), StreamEx.of("a", "b").toList()); assertEquals(asList("a", "b"), StreamEx.of(asList("a", "b")).toList()); assertEquals(asList("a", "b"), StreamEx.of(asList("a", "b").stream()).toList()); assertEquals(asList("a", "b"), StreamEx.split("a,b", ",").toList()); assertEquals(asList("a", "c", "d"), StreamEx.split("abcBd", Pattern.compile("b", Pattern.CASE_INSENSITIVE)) .toList()); assertEquals(asList("a", "b"), StreamEx.ofLines(new StringReader("a\nb")).toList()); assertEquals(asList("a", "b"), StreamEx.ofLines(new BufferedReader(new StringReader("a\nb"))).toList()); assertEquals(asList("a", "b"), StreamEx.ofLines(getReader()).toList()); assertEquals(asList("a", "a", "a", "a"), StreamEx.generate(() -> "a").limit(4).toList()); assertEquals(asList("a", "a", "a", "a"), StreamEx.constant("a", 4).toList()); assertEquals(asList("c", "d", "e"), StreamEx.of("abcdef".split(""), 2, 5).toList()); StreamEx<String> stream = StreamEx.of("foo", "bar"); assertSame(stream.stream(), StreamEx.of(stream).stream()); assertEquals(asList("a1", "b2", "c3"), StreamEx.zip(asList("a", "b", "c"), asList(1, 2, 3), (s, i) -> s + i) .toList()); assertEquals(asList("a1", "b2", "c3"), StreamEx.zip(new String[] { "a", "b", "c" }, new Integer[] { 1, 2, 3 }, ( s, i) -> s + i).toList()); assertEquals(asList("a", "b"), StreamEx.of(asList("a", "b").spliterator()).toList()); assertEquals(asList("a", "b"), StreamEx.of(asList("a", "b").iterator()).toList()); assertEquals(asList(), StreamEx.of(asList().iterator()).toList()); assertEquals(asList(), StreamEx.of(asList().iterator()).parallel().toList()); assertEquals(asList("a", "b"), StreamEx.of(new Vector<>(asList("a", "b")).elements()).toList()); assertEquals(asList("a", "b", "c", "d"), StreamEx.ofReversed(asList("d", "c", "b", "a")).toList()); assertEquals(asList("a", "b", "c", "d"), StreamEx.ofReversed(new String[] { "d", "c", "b", "a" }).toList()); } @Test public void testIterate() { assertEquals(asList("a", "aa", "aaa", "aaaa"), StreamEx.iterate("a", x -> x + "a").limit(4).toList()); assertEquals(asList("a", "aa", "aaa", "aaaa"), StreamEx.iterate("a", x -> x.length() <= 4, x -> x + "a") .toList()); assertFalse(StreamEx.iterate("a", x -> x.length() <= 10, x -> x + "a").has("b")); assertEquals(0, StreamEx.iterate("", x -> !x.isEmpty(), x -> x.substring(1)).count()); checkSpliterator("iterate", () -> StreamEx.iterate(1, x -> x < 100, x -> x * 2).spliterator()); } @Test public void testCreateFromFile() throws IOException { File f = tmp.newFile(); List<String> input = asList("Some", "Test", "Lines"); Files.write(f.toPath(), input); assertEquals(input, StreamEx.ofLines(f.toPath()).toList()); Files.write(f.toPath(), input, StandardCharsets.UTF_16); assertEquals(input, StreamEx.ofLines(f.toPath(), StandardCharsets.UTF_16).toList()); } private Reader getReader() { return new BufferedReader(new StringReader("a\nb")); } @Test public void testReader() { String input = IntStreamEx.range(5000).joining("\n"); List<String> expectedList = IntStreamEx.range(1, 5000).mapToObj(String::valueOf).toList(); Set<String> expectedSet = IntStreamEx.range(1, 5000).mapToObj(String::valueOf).toSet(); // Saving actual to separate variable helps to work-around // javac <8u40 issue JDK-8056984 List<String> actualList = StreamEx.ofLines(new StringReader(input)).skip(1).parallel().toList(); assertEquals(expectedList, actualList); actualList = StreamEx.ofLines(new StringReader(input)).pairMap((a, b) -> b).parallel().toList(); assertEquals(expectedList, actualList); Set<String> actualSet = StreamEx.ofLines(new StringReader(input)).pairMap((a, b) -> b).parallel().toSet(); assertEquals(expectedSet, actualSet); actualSet = StreamEx.ofLines(new StringReader(input)).skip(1).parallel().toCollection(HashSet::new); assertEquals(expectedSet, actualSet); actualSet = StreamEx.ofLines(new StringReader(input)).parallel().skipOrdered(1).toSet(); assertEquals(expectedSet, actualSet); actualSet = StreamEx.ofLines(new StringReader(input)).skipOrdered(1).parallel().toSet(); assertEquals(expectedSet, actualSet); assertFalse(StreamEx.ofLines(new StringReader(input)).spliterator().getClass().getSimpleName().endsWith( "IteratorSpliterator")); } @Test(expected = IllegalArgumentException.class) public void testZipThrows() { StreamEx.zip(asList("A"), asList("b", "c"), String::concat); } @Test public void testBasics() { assertFalse(StreamEx.of("a").isParallel()); assertTrue(StreamEx.of("a").parallel().isParallel()); assertFalse(StreamEx.of("a").parallel().sequential().isParallel()); AtomicInteger i = new AtomicInteger(); try (Stream<String> s = StreamEx.of("a").onClose(i::incrementAndGet)) { assertEquals(1, s.count()); } assertEquals(1, i.get()); assertEquals(asList(1, 2), StreamEx.of("a", "bb").map(String::length).toList()); assertFalse(StreamEx.empty().findAny().isPresent()); assertEquals("a", StreamEx.of("a").findAny().get()); assertFalse(StreamEx.empty().findFirst().isPresent()); assertEquals("a", StreamEx.of("a", "b").findFirst().get()); assertEquals(asList("b", "c"), StreamEx.of("a", "b", "c").skip(1).toList()); AtomicBoolean b = new AtomicBoolean(false); try (Stream<String> stream = StreamEx.of("a").onClose(() -> b.set(true))) { assertFalse(b.get()); assertEquals(1, stream.count()); assertFalse(b.get()); } assertTrue(b.get()); assertTrue(StreamEx.of("a", "b").anyMatch("a"::equals)); assertFalse(StreamEx.of("a", "b").anyMatch("c"::equals)); assertFalse(StreamEx.of("a", "b").allMatch("a"::equals)); assertFalse(StreamEx.of("a", "b").allMatch("c"::equals)); assertFalse(StreamEx.of("a", "b").noneMatch("a"::equals)); assertTrue(StreamEx.of("a", "b").noneMatch("c"::equals)); assertTrue(StreamEx.of().noneMatch("a"::equals)); assertTrue(StreamEx.of().allMatch("a"::equals)); assertFalse(StreamEx.of().anyMatch("a"::equals)); assertEquals("abbccc", StreamEx.of("a", "bb", "ccc").collect(StringBuilder::new, StringBuilder::append, StringBuilder::append).toString()); assertArrayEquals(new String[] { "a", "b", "c" }, StreamEx.of("a", "b", "c").toArray(String[]::new)); assertArrayEquals(new Object[] { "a", "b", "c" }, StreamEx.of("a", "b", "c").toArray()); assertEquals(3, StreamEx.of("a", "b", "c").spliterator().getExactSizeIfKnown()); assertTrue(StreamEx.of("a", "b", "c").spliterator().hasCharacteristics(Spliterator.ORDERED)); assertFalse(StreamEx.of("a", "b", "c").unordered().spliterator().hasCharacteristics(Spliterator.ORDERED)); } @Test public void testCovariance() { StreamEx<Number> stream = StreamEx.of(1, 2, 3); List<Number> list = stream.toList(); assertEquals(asList(1, 2, 3), list); StreamEx<Object> objStream = StreamEx.of(list.spliterator()); List<Object> objList = objStream.toList(); assertEquals(asList(1, 2, 3), objList); } @Test public void testToList() { List<Integer> list = StreamEx.of(1, 2, 3).toList(); // Test that returned list is mutable List<Integer> list2 = StreamEx.of(4, 5, 6).parallel().toList(); list2.add(7); list.addAll(list2); assertEquals(asList(1, 2, 3, 4, 5, 6, 7), list); } @Test public void testToArray() { Number[] numbers = StreamEx.of(1, 2, 3).toArray(Number.class); assertArrayEquals(new Number[] { 1, 2, 3 }, numbers); assertEquals(Number.class, numbers.getClass().getComponentType()); Integer[] emptyArray = {}; assertSame(emptyArray, StreamEx.of(1, 2, 3).filter(x -> x > 3).toArray(emptyArray)); assertArrayEquals(new Integer[] { 1, 2, 3 }, StreamEx.of(1, 2, 3).remove(x -> x > 3).toArray(emptyArray)); } @Test public void testForEach() { List<Integer> list = new ArrayList<>(); StreamEx.of(1, 2, 3).forEach(list::add); assertEquals(asList(1, 2, 3), list); StreamEx.of(1, 2, 3).forEachOrdered(list::add); assertEquals(asList(1, 2, 3, 1, 2, 3), list); StreamEx.of(1, 2, 3).parallel().forEachOrdered(list::add); assertEquals(asList(1, 2, 3, 1, 2, 3, 1, 2, 3), list); } @Test public void testFlatMap() { assertArrayEquals(new int[] { 0, 0, 1, 0, 0, 1, 0, 0 }, StreamEx.of("111", "222", "333").flatMapToInt(s -> s .chars().map(ch -> ch - '0')).pairMap((a, b) -> b - a).toArray()); assertArrayEquals(new long[] { 0, 0, 1, 0, 0, 1, 0, 0 }, StreamEx.of("111", "222", "333").flatMapToLong(s -> s .chars().mapToLong(ch -> ch - '0')).pairMap((a, b) -> b - a).toArray()); assertArrayEquals(new double[] { 0, 0, 1, 0, 0, 1, 0, 0 }, StreamEx.of("111", "222", "333").flatMapToDouble( s -> s.chars().mapToDouble(ch -> ch - '0')).pairMap((a, b) -> b - a).toArray(), 0.0); } @Test public void testAndThen() { HashSet<String> set = StreamEx.of("a", "bb", "ccc").toListAndThen(HashSet<String>::new); assertEquals(3, set.size()); assertTrue(set.contains("bb")); ArrayList<String> list = StreamEx.of("a", "bb", "ccc").toSetAndThen(ArrayList<String>::new); assertEquals(3, list.size()); assertTrue(list.contains("bb")); } @Test public void testToMap() { Map<String, Integer> expected = new HashMap<>(); expected.put("a", 1); expected.put("bb", 2); expected.put("ccc", 3); Map<Integer, String> expected2 = new HashMap<>(); expected2.put(1, "a"); expected2.put(2, "bb"); expected2.put(3, "ccc"); streamEx(() -> Stream.of("a", "bb", "ccc"), supplier -> { Map<String, Integer> map = supplier.get().toMap(String::length); assertEquals(supplier.get().isParallel(), map instanceof ConcurrentMap); assertEquals(expected, map); Map<Integer, String> map2 = supplier.get().toMap(String::length, Function.identity()); assertEquals(supplier.get().isParallel(), map2 instanceof ConcurrentMap); assertEquals(expected2, map2); }); Map<Integer, String> expected3 = new HashMap<>(); expected3.put(1, "a"); expected3.put(2, "bbdd"); expected3.put(3, "ccc"); streamEx(() -> Stream.of("a", "bb", "ccc", "dd"), supplier -> { Map<Integer, String> seqMap3 = supplier.get().toMap(String::length, Function.identity(), String::concat); assertEquals(expected3, seqMap3); checkIllegalStateException(() -> supplier.get().toMap(String::length, Function.identity()), "2", "dd", "bb"); }); } @Test public void testToSortedMap() { Map<String, Integer> expected = new HashMap<>(); expected.put("a", 1); expected.put("bb", 2); expected.put("ccc", 3); Map<Integer, String> expected2 = new HashMap<>(); expected2.put(1, "a"); expected2.put(2, "bb"); expected2.put(3, "ccc"); streamEx(() -> Stream.of("a", "bb", "ccc"), supplier -> { SortedMap<String, Integer> map = supplier.get().toSortedMap(String::length); assertEquals(supplier.get().isParallel(), map instanceof ConcurrentMap); assertEquals(expected, map); SortedMap<Integer, String> map2 = supplier.get().toSortedMap(String::length, Function.identity()); assertEquals(supplier.get().isParallel(), map2 instanceof ConcurrentMap); assertEquals(expected2, map2); }); Map<Integer, String> expected3 = new HashMap<>(); expected3.put(1, "a"); expected3.put(2, "bbdd"); expected3.put(3, "ccc"); streamEx(() -> Stream.of("a", "bb", "ccc", "dd"), supplier -> { SortedMap<Integer, String> seqMap3 = supplier.get().toSortedMap(String::length, Function.identity(), String::concat); assertEquals(supplier.toString(), expected3, seqMap3); checkIllegalStateException(() -> supplier.get().toSortedMap(String::length, Function.identity()), "2", "dd", "bb"); }); } @Test public void testToNavigableMap() { Map<String, Integer> expected = new HashMap<>(); expected.put("a", 1); expected.put("bb", 2); expected.put("ccc", 3); Map<Integer, String> expected2 = new HashMap<>(); expected2.put(1, "a"); expected2.put(2, "bb"); expected2.put(3, "ccc"); streamEx(() -> Stream.of("a", "bb", "ccc"), supplier -> { NavigableMap<String, Integer> map = supplier.get().toNavigableMap(String::length); assertEquals(supplier.get().isParallel(), map instanceof ConcurrentMap); assertEquals(expected, map); NavigableMap<Integer, String> map2 = supplier.get().toNavigableMap(String::length, Function.identity()); assertEquals(supplier.get().isParallel(), map2 instanceof ConcurrentMap); assertEquals(expected2, map2); }); Map<Integer, String> expected3 = new HashMap<>(); expected3.put(1, "a"); expected3.put(2, "bbdd"); expected3.put(3, "ccc"); streamEx(() -> Stream.of("a", "bb", "ccc", "dd"), supplier -> { NavigableMap<Integer, String> seqMap3 = supplier.get().toNavigableMap(String::length, Function.identity(), String::concat); assertEquals(supplier.toString(), expected3, seqMap3); checkIllegalStateException(() -> supplier.get().toNavigableMap(String::length, Function.identity()), "2", "dd", "bb"); }); } @Test public void testGroupingBy() { Map<Integer, List<String>> expected = new HashMap<>(); expected.put(1, asList("a")); expected.put(2, asList("bb", "dd")); expected.put(3, asList("ccc")); Map<Integer, Set<String>> expectedMapSet = new HashMap<>(); expectedMapSet.put(1, new HashSet<>(asList("a"))); expectedMapSet.put(2, new HashSet<>(asList("bb", "dd"))); expectedMapSet.put(3, new HashSet<>(asList("ccc"))); streamEx(() -> StreamEx.of("a", "bb", "dd", "ccc"), supplier -> { assertEquals(expected, supplier.get().groupingBy(String::length)); Map<Integer, List<String>> map = supplier.get().groupingTo(String::length, LinkedList::new); assertEquals(expected, map); assertTrue(map.get(1) instanceof LinkedList); assertEquals(expectedMapSet, supplier.get().groupingBy(String::length, Collectors.toSet())); assertEquals(expectedMapSet, supplier.get().groupingBy(String::length, HashMap::new, Collectors.toSet())); ConcurrentHashMap<Integer, Set<String>> chm = supplier.get().groupingBy(String::length, ConcurrentHashMap::new, Collectors.toSet()); assertEquals(expectedMapSet, chm); chm = supplier.get().groupingTo(String::length, ConcurrentHashMap::new, TreeSet::new); assertTrue(chm.get(1) instanceof TreeSet); }); } @Test public void testPartitioning() { Map<Boolean, List<String>> map = StreamEx.of("a", "bb", "c", "dd").partitioningBy(s -> s.length() > 1); assertEquals(asList("bb", "dd"), map.get(true)); assertEquals(asList("a", "c"), map.get(false)); Map<Boolean, Long> counts = StreamEx.of("a", "bb", "c", "dd", "eee").partitioningBy(s -> s.length() > 1, Collectors.counting()); assertEquals(3L, (long) counts.get(true)); assertEquals(2L, (long) counts.get(false)); Map<Boolean, List<String>> mapLinked = StreamEx.of("a", "bb", "c", "dd").partitioningTo(s -> s.length() > 1, LinkedList::new); assertEquals(asList("bb", "dd"), mapLinked.get(true)); assertEquals(asList("a", "c"), mapLinked.get(false)); assertTrue(mapLinked.get(true) instanceof LinkedList); } @Test public void testIterable() { List<String> result = new ArrayList<>(); for (String s : StreamEx.of("a", "b", "cc").filter(s -> s.length() < 2)) { result.add(s); } assertEquals(asList("a", "b"), result); } @Test public void testCreateFromMap() { Map<String, Integer> data = new LinkedHashMap<>(); data.put("aaa", 10); data.put("bb", 25); data.put("c", 37); assertEquals(asList("aaa", "bb", "c"), StreamEx.ofKeys(data).toList()); assertEquals(asList("aaa"), StreamEx.ofKeys(data, x -> x % 2 == 0).toList()); assertEquals(asList(10, 25, 37), StreamEx.ofValues(data).toList()); assertEquals(asList(10, 25), StreamEx.ofValues(data, s -> s.length() > 1).toList()); } @Test public void testSelect() { assertEquals(asList("a", "b"), StreamEx.of(1, "a", 2, "b", 3, "cc").select(String.class).filter(s -> s .length() == 1).toList()); StringBuilder sb = new StringBuilder(); StringBuffer sbb = new StringBuffer(); StreamEx.<CharSequence> of("test", sb, sbb).select(Appendable.class).forEach(a -> { try { a.append("b"); } catch (IOException e) { throw new UncheckedIOException(e); } }); assertEquals("b", sb.toString()); assertEquals("b", sbb.toString()); } @Test public void testFlatCollection() { Map<Integer, List<String>> data = new LinkedHashMap<>(); data.put(1, asList("a", "b")); data.put(2, asList("c", "d")); data.put(3, null); assertEquals(asList("a", "b", "c", "d"), StreamEx.of(data.entrySet()).flatCollection(Entry::getValue).toList()); } @Test public void testFlatArray() { Map<Integer, String[]> data = new LinkedHashMap<>(); data.put(1, new String[] {"a", "b"}); data.put(2, new String[] {"c", "d"}); data.put(3, null); assertEquals(asList("a", "b", "c", "d"), StreamEx.of(data.entrySet()).flatArray(Entry::getValue).toList()); } @Test public void testAppend() { assertEquals(asList("a", "b", "c", "d", "e"), StreamEx.of("a", "b", "c", "dd").remove(s -> s.length() > 1) .append("d", "e").toList()); assertEquals(asList("a", "b", "c", "d", "e"), StreamEx.of("a", "b", "c").append(asList("d", "e").stream()) .toList()); assertEquals(asList("a", "b", "c", "d", "e"), StreamEx.of("a", "b", "c").append(asList("d", "e")).toList()); List<Integer> list = asList(1, 2, 3, 4); assertEquals(asList(1.0, 2, 3L, 1, 2, 3, 4), StreamEx.of(1.0, 2, 3L).append(list).toList()); StreamEx<Integer> s = StreamEx.of(1, 2, 3); assertSame(s, s.append()); assertSame(s, s.append(Collections.emptyList())); assertSame(s, s.append(new ArrayList<>())); assertSame(s, s.append(Stream.empty())); assertNotSame(s, s.append(new ConcurrentLinkedQueue<>())); } @Test public void testPrepend() { Supplier<Stream<String>> sized = () -> StreamEx.of("a", "b", "c", "dd"); Supplier<Stream<String>> notSized = () -> StreamEx.of(StreamEx.of("a", "b", "c", "dd").iterator()); for (Supplier<Stream<String>> supplier : asList(sized, notSized)) { streamEx(supplier, s -> { assertEquals(asList("d", "e", "a", "b", "c"), s.get().remove(str -> str.length() > 1).prepend("d", "e") .toList()); assertEquals(asList("d", "e", "a", "b", "c", "dd"), s.get().prepend(asList("d", "e").stream()) .toList()); assertEquals(asList("d", "e", "a", "b", "c", "dd"), s.get().prepend(asList("d", "e")).toList()); }); } assertArrayEquals(new Object[] { 1, 2, 3, 1, 1 }, StreamEx.constant(1, Long.MAX_VALUE - 1).prepend(1, 2, 3) .limit(5).toArray()); assertEquals(asList(4, 3, 2, 1), StreamEx.of(1).prepend(2).prepend(StreamEx.of(3).prepend(4)).toList()); StreamEx<Integer> s = StreamEx.of(1, 2, 3); assertSame(s, s.prepend()); assertSame(s, s.prepend(Collections.emptyList())); assertSame(s, s.prepend(new ArrayList<>())); assertSame(s, s.prepend(Stream.empty())); assertNotSame(s, s.prepend(new ConcurrentLinkedQueue<>())); assertTrue(StreamEx.of("a", "b").prepend(Stream.of("c").parallel()).isParallel()); assertTrue(StreamEx.of("a", "b").parallel().prepend(Stream.of("c").parallel()).isParallel()); assertTrue(StreamEx.of("a", "b").parallel().prepend(Stream.of("c")).isParallel()); assertFalse(StreamEx.of("a", "b").prepend(Stream.of("c")).isParallel()); } @Test public void testPrependTSO() { List<Integer> expected = IntStreamEx.rangeClosed(19999, 0, -1).boxed().toList(); assertEquals(expected, IntStreamEx.range(20000).mapToObj(StreamEx::of).reduce(StreamEx::prepend).get() .toList()); assertEquals(expected, IntStreamEx.range(20000).parallel().mapToObj(StreamEx::of).reduce(StreamEx::prepend) .get().toList()); } @Test public void testNonNull() { List<String> data = asList("a", null, "b"); assertEquals(asList("a", null, "b"), StreamEx.of(data).toList()); assertEquals(asList("a", "b"), StreamEx.of(data).nonNull().toList()); } @Test public void testSorting() { assertEquals(asList("a", "b", "c", "d"), StreamEx.of("b", "c", "a", "d").sorted().toList()); assertEquals(asList("d", "c", "b", "a"), StreamEx.of("b", "c", "a", "d").reverseSorted().toList()); List<String> data = asList("a", "bbb", "cc"); assertEquals(asList("a", "cc", "bbb"), StreamEx.of(data).sorted(Comparator.comparingInt(String::length)) .toList()); assertEquals(asList("bbb", "cc", "a"), StreamEx.of(data).reverseSorted(Comparator.comparingInt(String::length)) .toList()); assertEquals(asList("a", "cc", "bbb"), StreamEx.of(data).sortedByInt(String::length).toList()); assertEquals(asList("a", "cc", "bbb"), StreamEx.of(data).sortedByLong(String::length).toList()); assertEquals(asList("a", "cc", "bbb"), StreamEx.of(data).sortedByDouble(String::length).toList()); assertEquals(asList("a", "cc", "bbb"), StreamEx.of(data).sortedBy(String::length).toList()); } @Test public void testMinMax() { withRandom(random -> { List<String> data = IntStreamEx.of(random, 1000, 1, 100).mapToObj(len -> IntStreamEx.constant(random .nextInt('z' - 'a' + 1) + 'a', len).charsToString()).toList(); String minStr = Collections.min(data, Comparator.comparingInt(String::length)), maxStr = Collections.max( data, Comparator.comparingInt(String::length)); streamEx(data::stream, supplier -> { assertEquals(supplier.toString(), maxStr, supplier.get().max(Comparator.comparingInt(String::length)) .get()); assertEquals(supplier.toString(), maxStr, supplier.get().maxByInt(String::length).get()); assertEquals(supplier.toString(), maxStr, supplier.get().maxByLong(String::length).get()); assertEquals(supplier.toString(), maxStr, supplier.get().maxByDouble(String::length).get()); assertEquals(supplier.toString(), maxStr, supplier.get().maxBy(String::length).get()); assertEquals(supplier.toString(), maxStr, supplier.get().min(Comparator.comparingInt(String::length) .reversed()).get()); assertEquals(supplier.toString(), minStr, supplier.get().minByInt(String::length).get()); assertEquals(supplier.toString(), minStr, supplier.get().minByLong(String::length).get()); assertEquals(supplier.toString(), minStr, supplier.get().minByDouble(String::length).get()); assertEquals(supplier.toString(), minStr, supplier.get().minBy(String::length).get()); }); assertFalse(StreamEx.<String> empty().minByInt(String::length).isPresent()); }); } @Test public void testFind() { assertEquals("bb", StreamEx.of("a", "bb", "c").findFirst(s -> s.length() == 2).get()); assertFalse(StreamEx.of("a", "bb", "c").findFirst(s -> s.length() == 3).isPresent()); } @Test public void testHas() { assertTrue(StreamEx.of("a", "bb", "c").has("bb")); assertFalse(StreamEx.of("a", "bb", "c").has("cc")); assertFalse(StreamEx.of("a", "bb", "c").has(null)); assertTrue(StreamEx.of("a", "bb", null, "c").has(null)); } @Test public void testWithout() { assertEquals(asList("a", "bb", null), StreamEx.of("a", "bb", null, "c").without("c").toList()); String s = null; assertEquals(asList("a", "bb", "c"), StreamEx.of("a", "bb", null, "c", null).without(s).toList()); assertTrue(StreamEx.of("bb", "bb", "bb").without("bb").toList().isEmpty()); assertEquals(asList("bb", "bb", "bb"), StreamEx.of("bb", "bb", "bb").without(s).toList()); StreamEx<String> stream = StreamEx.of("a", "b", "c"); assertSame(stream, stream.without()); assertEquals(asList("a", "b", "c"), StreamEx.of("a", "b", null, "c").without(new String[] { null }).toList()); assertEquals(asList(), StreamEx.of("a", "b", null, "c").without("c", null, "b", "a").toList()); } @Test public void testJoining() { assertEquals("abc", StreamEx.of("a", "b", "c").joining()); assertEquals("a,b,c", StreamEx.of("a", "b", "c").joining(",")); assertEquals("[1;2;3]", StreamEx.of(1, 2, 3).joining(";", "[", "]")); withRandom(r -> { List<Integer> input1 = IntStreamEx.of(r, 1000, 0, 1000).boxed().toList(); List<String> input2 = IntStreamEx.of(r, 1000, 0, 1000).mapToObj(String::valueOf).toList(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < input1.size(); i++) { if (sb.length() > 0) sb.append(','); sb.append(input1.get(i)).append(':').append(input2.get(i)); } String expected = sb.toString(); assertEquals(expected, StreamEx.zip(input1, input2, (i, s) -> i + ":" + s).joining(",")); assertEquals(expected, StreamEx.zip(input1, input2, (i, s) -> i + ":" + s).parallel().joining(",")); }); } @Test public void testFoldLeft() { List<String> input = asList("a", "bb", "ccc"); streamEx(input::stream, supplier -> { assertEquals("ccc;bb;a;", supplier.get().foldLeft("", (u, v) -> v + ";" + u)); // Removing types here causes internal error in Javac compiler // java.lang.AssertionError: attribution shouldn't be happening here // Bug appears in javac 1.8.0.20 and javac 1.8.0.45 // javac 1.9.0b55 and ecj compiles normally // Probably this ticket: // https://bugs.openjdk.java.net/browse/JDK-8068399 assertTrue(supplier.get().foldLeft(false, (Boolean acc, String s) -> acc || s.equals("bb"))); assertFalse(supplier.get().foldLeft(false, (Boolean acc, String s) -> acc || s.equals("d"))); assertEquals(6, (int) supplier.get().foldLeft(0, (acc, v) -> acc + v.length())); assertEquals("{ccc={bb={a={}}}}", supplier.get().foldLeft(Collections.emptyMap(), (Map<String, Object> acc, String v) -> Collections.singletonMap(v, acc)).toString()); }); } @Test public void testFoldLeftOptional() { // non-associative BinaryOperator<Integer> accumulator = (x, y) -> (x + y) * (x + y); streamEx(() -> StreamEx.constant(3, 4), supplier -> assertEquals(2322576, (int) supplier.get().foldLeft( accumulator).orElse(-1))); streamEx(() -> StreamEx.of(1, 2, 3), supplier -> assertEquals(144, (int) supplier.get().foldLeft(accumulator) .orElse(-1))); emptyStreamEx(Integer.class, supplier -> assertFalse(supplier.get().foldLeft(accumulator).isPresent())); } @Test public void testFoldRight() { assertEquals(";c;b;a", StreamEx.of("a", "b", "c").parallel().foldRight("", (u, v) -> v + ";" + u)); assertEquals("{a={bb={ccc={}}}}", StreamEx.of("a", "bb", "ccc").foldRight(Collections.emptyMap(), (BiFunction<String, Map<String, Object>, Map<String, Object>>) Collections::singletonMap).toString()); assertEquals("{a={bb={ccc={}}}}", StreamEx.of("a", "bb", "ccc").parallel().foldRight(Collections.emptyMap(), (BiFunction<String, Map<String, Object>, Map<String, Object>>) Collections::singletonMap).toString()); } @Test public void testFoldRightOptional() { // non-associative BinaryOperator<Integer> accumulator = (x, y) -> (x + y) * (x + y); streamEx(() -> StreamEx.constant(3, 4), supplier -> assertEquals(2322576, (int) supplier.get().foldRight( accumulator).orElse(-1))); streamEx(() -> StreamEx.of(1, 2, 3, 0), supplier -> assertEquals(14884, (int) supplier.get().foldRight( accumulator).orElse(-1))); emptyStreamEx(Integer.class, supplier -> assertFalse(supplier.get().foldRight(accumulator).isPresent())); } @Test public void testDistinctAtLeast() { assertEquals(0, StreamEx.of("a", "b", "c").distinct(2).count()); assertEquals(StreamEx.of("a", "b", "c").distinct().toList(), StreamEx.of("a", "b", "c").distinct(1).toList()); assertEquals(asList("b"), StreamEx.of("a", "b", "c", "b", null).distinct(2).toList()); assertEquals(asList("b", null), StreamEx.of("a", "b", null, "c", "b", null).distinct(2).toList()); assertEquals(asList(null, "b"), StreamEx.of("a", "b", null, "c", null, "b", null, "b").distinct(2).toList()); streamEx(() -> IntStreamEx.range(0, 1000).map(x -> x / 3).boxed(), supplier -> { assertEquals(334, supplier.get().distinct().count()); assertEquals(333, supplier.get().distinct(2).count()); assertEquals(333, supplier.get().distinct(3).count()); assertEquals(0, supplier.get().distinct(4).count()); List<Integer> distinct3List = supplier.get().distinct(3).toList(); assertEquals(333, distinct3List.size()); Map<Integer, Long> map = supplier.get().collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting())); List<Integer> expectedList = StreamEx.ofKeys(map, val -> val >= 3).toList(); assertEquals(333, expectedList.size()); assertEquals(distinct3List, expectedList); }); assertEquals(0, StreamEx.of("a", "b", "c").parallel().distinct(2).count()); assertEquals(StreamEx.of("a", "b", "c").parallel().distinct().toList(), StreamEx.of("a", "b", "c").parallel() .distinct(1).toList()); assertEquals(asList("b"), StreamEx.of("a", "b", "c", "b").parallel().distinct(2).toList()); assertEquals(new HashSet<>(asList("b", null)), StreamEx.of("a", "b", null, "c", "b", null).parallel().distinct( 2).toSet()); assertEquals(new HashSet<>(asList(null, "b")), StreamEx.of("a", "b", null, "c", null, "b", null, "b").parallel() .distinct(2).toSet()); for (int i = 1; i < 1000; i += 100) { List<Integer> input = IntStreamEx.of(new Random(1), i, 1, 100).boxed().toList(); for (int n : IntStreamEx.range(2, 10).boxed()) { Set<Integer> expected = input.stream().collect(Collectors.collectingAndThen(Collectors.groupingBy( Function.identity(), Collectors.counting()), m -> { m.values().removeIf(l -> l < n); return m.keySet(); })); assertEquals(expected, StreamEx.of(input).distinct(n).toSet()); assertEquals(expected, StreamEx.of(input).parallel().distinct(n).toSet()); assertEquals(0, StreamEx.of(expected).distinct(2).toSet().size()); } } assertEquals(IntStreamEx.range(10).boxed().toList(), IntStreamEx.range(100).mapToObj(x -> x / 10).sorted() .distinct(3).sorted().toList()); // Saving actual to separate variable helps to work-around // javac <8u40 issue JDK-8056984 List<String> actual = StreamEx.split("a,b,a,c,d,b,a", ",").parallel().distinct(2).sorted().toList(); assertEquals(asList("a", "b"), actual); } @Test public void testDistinctAtLeastPairMap() { int last = -1; int cur = -1; int count = 0; List<Integer> expected = new ArrayList<>(); for (int i : IntStreamEx.of(new Random(1), 1000, 0, 100).sorted().boxed()) { if (i == cur) { count++; if (count == 15) { if (last >= 0) { expected.add(cur - last); } last = cur; } } else { count = 1; cur = i; } } streamEx(() -> new Random(1).ints(1000, 0, 100).sorted().boxed(), supplier -> assertEquals(expected, supplier .get().distinct(15).pairMap((a, b) -> b - a).toList())); } private <T extends Comparable<? super T>> boolean isSorted(Collection<T> c) { return StreamEx.of(c).parallel().pairMap(Comparable::compareTo).allMatch(r -> r <= 0); } private <T extends Comparable<? super T>> Optional<T> firstMisplaced(Collection<T> c) { return StreamEx.of(c).parallel().pairMap((a, b) -> a.compareTo(b) > 0 ? a : null).nonNull().findFirst(); } static class Point { double x, y; Point(double x, double y) { this.x = x; this.y = y; } double distance(Point o) { return Math.sqrt((x - o.x) * (x - o.x) + (y - o.y) * (y - o.y)); } } @Test public void testPairMap() { assertEquals(0, StreamEx.<String> empty().pairMap(String::concat).count()); assertArrayEquals(new Object[0], StreamEx.<String> empty().pairMap(String::concat).toArray()); assertEquals(0, StreamEx.of("a").pairMap(String::concat).count()); assertEquals(asList("aa", "aa", "aa"), StreamEx.generate(() -> "a").pairMap(String::concat).limit(3).toList()); AtomicBoolean flag = new AtomicBoolean(); assertFalse(flag.get()); StreamEx<String> stream = StreamEx.of("a", "b").onClose(() -> flag.set(true)).pairMap(String::concat); stream.close(); assertTrue(flag.get()); assertEquals(Collections.singletonMap(1, 1999L), IntStreamEx.range(2000).boxed().pairMap((a, b) -> b - a) .groupingBy(Function.identity(), Collectors.counting())); assertEquals(Collections.singletonMap(1, 1999L), IntStreamEx.range(2000).parallel().boxed().pairMap((a, b) -> b - a).groupingBy(Function.identity(), Collectors.counting())); withRandom(r -> { Integer[] data = r.ints(1000, 1, 1000).boxed().toArray(Integer[]::new); Double[] expected = new Double[data.length - 1]; for (int i = 0; i < expected.length; i++) expected[i] = (data[i + 1] - data[i]) * 1.23; Double[] result = StreamEx.of(data).parallel().pairMap((a, b) -> (b - a) * 1.23).toArray(Double[]::new); assertArrayEquals(expected, result); result = StreamEx.of(data).pairMap((a, b) -> (b - a) * 1.23).toArray(Double[]::new); assertArrayEquals(expected, result); }); // Find all numbers where the integer preceded a larger value. Collection<Integer> numbers = asList(10, 1, 15, 30, 2, 6); List<Integer> res = StreamEx.of(numbers).pairMap((a, b) -> a < b ? a : null).nonNull().toList(); assertEquals(asList(1, 15, 2), res); // Check whether stream is sorted assertTrue(isSorted(asList("a", "bb", "bb", "c"))); assertFalse(isSorted(asList("a", "bb", "bb", "bba", "bb", "c"))); withRandom(r -> assertTrue(isSorted(IntStreamEx.of(r).boxed().distinct().limit(1000).toCollection( TreeSet::new)))); // Find first element which violates the sorting assertEquals("bba", firstMisplaced(asList("a", "bb", "bb", "bba", "bb", "c")).get()); assertFalse(firstMisplaced(asList("a", "bb", "bb", "bb", "c")).isPresent()); assertFalse(firstMisplaced(Arrays.<String> asList()).isPresent()); assertFalse(IntStreamEx.range(1000).greater(2000).boxed().parallel().pairMap((a, b) -> a).findFirst() .isPresent()); } @Test public void testPairMapCornerCase() { repeat(100, iter -> streamEx(() -> IntStreamEx.range(1000).filter(x -> x == 0 || x == 999).boxed(), supplier -> assertEquals(Collections.singletonList(-999), supplier.get().pairMap((a, b) -> a - b) .toList()))); } @Test public void testPairMapFlatMapBug() { Integer[][] input = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 7, 8 }, { 9 } }; streamEx(() -> StreamEx.of(input).<Integer> flatMap(Arrays::stream), supplier -> assertEquals(1L, supplier.get() .pairMap((a, b) -> b - a).distinct().count())); } private double interpolate(Point[] points, double x) { return StreamEx.of(points).parallel().pairMap((p1, p2) -> p1.x <= x && p2.x >= x ? (x - p1.x) / (p2.x - p1.x) * (p2.y - p1.y) + p1.y : null).nonNull().findAny().orElse(Double.NaN); } @Test public void testPairMapInterpolation() { Point[] points = IntStreamEx.range(1000).mapToObj(i -> new Point(i, i % 2 == 0 ? 1 : 0)).toArray(Point[]::new); assertEquals(1, interpolate(points, 10), 0.0); assertEquals(0, interpolate(points, 999), 0.0); assertTrue(Double.isNaN(interpolate(points, -10))); assertEquals(0.4, interpolate(points, 100.6), 0.000001); } @Test public void testScanLeftPairMap() { withRandom(r -> { int[] random = IntStreamEx.of(r, 1000).toArray(); List<Integer> scanLeft = IntStreamEx.of(random).boxed().parallel().scanLeft(0, Integer::sum); assertArrayEquals(random, IntStreamEx.of(scanLeft).parallel().pairMap((a, b) -> (b - a)).toArray()); }); } @Test public void testPairMapCapitalization() { assertEquals("Test Capitalization Stream", IntStreamEx.ofChars("test caPiTaliZation streaM").parallel().prepend( 0).mapToObj(c -> (char) c).pairMap((c1, c2) -> !Character.isLetter(c1) && Character .isLetter(c2) ? Character.toTitleCase(c2) : Character.toLowerCase(c2)).joining()); } @Test public void testPairMapAddHeaders() { List<String> result = StreamEx.of("aaa", "abc", "bar", "foo", "baz", "argh").sorted().prepend("").pairMap((a, b) -> a.isEmpty() || a.charAt(0) != b.charAt(0) ? Stream.of("=== " + b.substring(0, 1).toUpperCase() + " ===", b) : Stream.of(b)).flatMap(Function.identity()).toList(); List<String> expected = asList("=== A ===", "aaa", "abc", "argh", "=== B ===", "bar", "baz", "=== F ===", "foo"); assertEquals(expected, result); } static class Node { Node parent; String name; public Node(String name) { this.name = name; } public void link(Node parent) { this.parent = parent; } @Override public String toString() { return parent == null ? name : parent + ":" + name; } } @Test public void testForPairs() { List<Node> nodes = StreamEx.of("one", "two", "three", "four").map(Node::new).toList(); StreamEx.of(nodes).forPairs(Node::link); assertEquals("four:three:two:one", nodes.get(0).toString()); nodes = StreamEx.of("one", "two", "three", "four").map(Node::new).toList(); StreamEx.of(nodes).parallel().forPairs(Node::link); assertEquals("four:three:two:one", nodes.get(0).toString()); } @Test public void testScanLeft() { streamEx(() -> IntStreamEx.rangeClosed(1, 4).boxed(), supplier -> { assertEquals(asList(0, 1, 3, 6, 10), supplier.get().scanLeft(0, Integer::sum)); assertEquals(asList(1, 3, 6, 10), supplier.get().scanLeft(Integer::sum)); }); emptyStreamEx(Integer.class, supplier -> { assertTrue(supplier.get().scanLeft(Integer::sum).isEmpty()); assertEquals(asList(0), supplier.get().scanLeft(0, Integer::sum)); }); assertEquals(167167000, IntStreamEx.rangeClosed(1, 1000).boxed().parallel().scanLeft(0, Integer::sum).stream() .mapToLong(x -> x).sum()); } @Test public void testScanRight() { streamEx(() -> IntStreamEx.rangeClosed(1, 4).boxed(), supplier -> { assertEquals(asList(10, 9, 7, 4, 0), supplier.get().scanRight(0, Integer::sum)); assertEquals(asList(10, 9, 7, 4), supplier.get().scanRight(Integer::sum)); }); emptyStreamEx(Integer.class, supplier -> { assertTrue(supplier.get().scanRight(Integer::sum).isEmpty()); assertEquals(asList(0), supplier.get().scanRight(0, Integer::sum)); }); assertEquals(333833500, IntStreamEx.rangeClosed(1, 1000).boxed().parallel().scanRight(0, Integer::sum).stream() .mapToLong(x -> x).sum()); } @Test public void testPermutations() { assertEquals("[]", StreamEx.ofPermutations(0).map(Arrays::toString).joining(";")); assertEquals("[0, 1, 2];[0, 2, 1];[1, 0, 2];[1, 2, 0];[2, 0, 1];[2, 1, 0]", StreamEx.ofPermutations(3).map( Arrays::toString).joining(";")); assertEquals(720, StreamEx.ofPermutations(7).parallel().filter(i -> i[3] == 5).count()); } static class TreeNode { String title; public TreeNode(String title) { this.title = title; } @Override public String toString() { return title; } public StreamEx<TreeNode> flatStream() { return StreamEx.ofTree(this, CompositeNode.class, CompositeNode::elements); } } static class CompositeNode extends TreeNode { List<TreeNode> nodes = new ArrayList<>(); public CompositeNode(String title) { super(title); } public CompositeNode add(TreeNode node) { nodes.add(node); return this; } public Stream<TreeNode> elements() { return nodes.stream(); } static CompositeNode createTestData() { CompositeNode r = new CompositeNode("root"); r.add(new CompositeNode("childA").add(new TreeNode("grandA1")).add(new TreeNode("grandA2"))); r.add(new CompositeNode("childB").add(new TreeNode("grandB1"))); r.add(new TreeNode("childC")); return r; } } @Test public void testOfTree() { String inputSimple = "bbb"; List<Object> input = asList("aa", null, asList(asList("bbbb", "cc", null, asList()), "ddd", asList("e"), asList( "fff")), "ggg"); @SuppressWarnings("unchecked") Function<Object, Stream<Object>> generator = o -> o instanceof List ? ((List<Object>) o).stream() : null; assertEquals("bbb", StreamEx.ofTree(inputSimple, generator).select(String.class).joining(",")); StreamEx<Object> ofTree = StreamEx.ofTree(input, generator); assertEquals("aa,bbbb,cc,ddd,e,fff,ggg", ofTree.select(String.class).joining(",")); assertEquals(14, StreamEx.ofTree(input, generator).select(List.class).mapToInt(List::size).sum()); CompositeNode r = CompositeNode.createTestData(); streamEx(r::flatStream, s -> { assertEquals("root,childA,grandA1,grandA2,childB,grandB1,childC", s.get().joining(",")); assertEquals(Optional.of("grandB1"), s.get().findFirst(tn -> tn.title.contains("B1")).map(tn -> tn.title)); assertEquals(Optional.empty(), s.get().findFirst(tn -> tn.title.contains("C1")).map(tn -> tn.title)); }); streamEx(() -> StreamEx.ofTree("", (String str) -> str.length() >= 3 ? null : Stream.of("a", "b").map(str::concat)), supplier -> { assertEquals(Arrays.asList("", "a", "aa", "aaa", "aab", "ab", "aba", "abb", "b", "ba", "baa", "bab", "bb", "bba", "bbb"), supplier.get().toList()); assertEquals(Arrays.asList("a", "b", "aa", "ab", "ba", "bb", "aaa", "aab", "aba", "abb", "baa", "bab", "bba", "bbb"), supplier.get().sortedByInt(String::length).without("").toList()); }); assertEquals(1000001, StreamEx.ofTree("x", s -> s.equals("x") ? IntStreamEx.range(1000000).mapToObj( String::valueOf) : null).parallel().count()); } @Test public void testOfTreeClose() { CompositeNode r = CompositeNode.createTestData(); r.flatStream().close(); // should not fail List<Consumer<StreamEx<TreeNode>>> tests = Arrays.<Consumer<StreamEx<TreeNode>>> asList(stream -> assertEquals( Optional.empty(), stream.findFirst(tn -> tn.title.contains("abc"))), stream -> assertEquals(Optional.of( "grandB1"), stream.findFirst(tn -> tn.title.contains("B1")).map(tn -> tn.title)), stream -> assertEquals(7, stream.count())); for (Consumer<StreamEx<TreeNode>> test : tests) { Set<String> set = new HashSet<>(); try (StreamEx<TreeNode> closableTree = StreamEx.ofTree(r, CompositeNode.class, cn -> cn.elements().onClose( () -> set.add(cn.title)))) { test.accept(closableTree); } assertEquals(set, StreamEx.of("root", "childA", "childB").toSet()); boolean catched = false; try (StreamEx<TreeNode> closableTree = StreamEx.ofTree(r, CompositeNode.class, cn -> cn.elements().onClose( () -> { if (!cn.title.equals("childA")) throw new IllegalArgumentException(cn.title); }))) { test.accept(closableTree); } catch (IllegalArgumentException ex) { catched = true; assertEquals("childB", ex.getMessage()); assertEquals(1, ex.getSuppressed().length); assertTrue(ex.getSuppressed()[0] instanceof IllegalArgumentException); assertEquals("root", ex.getSuppressed()[0].getMessage()); } assertTrue(catched); catched = false; try (StreamEx<TreeNode> closableTree = StreamEx.ofTree(r, CompositeNode.class, cn -> cn.elements().onClose( () -> { if (!cn.title.equals("childA")) throw new InternalError(cn.title); }))) { test.accept(closableTree); } catch (InternalError ex) { catched = true; assertEquals("childB", ex.getMessage()); assertEquals(1, ex.getSuppressed().length); assertTrue(ex.getSuppressed()[0] instanceof InternalError); assertEquals("root", ex.getSuppressed()[0].getMessage()); } assertTrue(catched); catched = false; try (StreamEx<TreeNode> closableTree = StreamEx.ofTree(r, CompositeNode.class, cn -> cn.elements().onClose( () -> { if (!cn.title.equals("childA")) throw new InternalError(cn.title); }))) { test.accept(closableTree.parallel()); } catch (InternalError ex) { catched = true; assertEquals(1, ex.getSuppressed().length); assertTrue(ex.getSuppressed()[0] instanceof InternalError); Set<String> msgSet = StreamEx.of(ex.getMessage(), ex.getSuppressed()[0].getMessage()).toSet(); assertTrue(msgSet.contains("root")); assertTrue(msgSet.contains("childB") || msgSet.contains("java.lang.InternalError: childB")); } assertTrue(catched); } } @Test public void testCross() { assertEquals("a-1, a-2, a-3, b-1, b-2, b-3, c-1, c-2, c-3", StreamEx.of("a", "b", "c").cross(1, 2, 3).join("-") .joining(", ")); assertEquals("a-1, b-1, c-1", StreamEx.of("a", "b", "c").cross(1).join("-").joining(", ")); assertEquals("", StreamEx.of("a", "b", "c").cross().join("-").joining(", ")); List<String> inputs = asList("i", "j", "k"); List<String> outputs = asList("x", "y", "z"); assertEquals("i->x, i->y, i->z, j->x, j->y, j->z, k->x, k->y, k->z", StreamEx.of(inputs).cross(outputs) .mapKeyValue((input, output) -> input + "->" + output).joining(", ")); assertEquals("", StreamEx.of(inputs).cross(Collections.emptyList()).join("->").joining(", ")); assertEquals("i-i, j-j, k-k", StreamEx.of(inputs).cross(Stream::of).join("-").joining(", ")); assertEquals("j-j, k-k", StreamEx.of(inputs).cross(x -> x.equals("i") ? null : Stream.of(x)).join("-").joining( ", ")); } @Test public void testCollapse() { streamEx(() -> StreamEx.constant(1, 1000), supplier -> assertEquals(Collections.singletonList(1), supplier.get() .collapse(Objects::equals).toList())); } @Test public void testCollapseEmptyLines() { withRandom(r -> repeat(100, i -> { List<String> input = IntStreamEx.range(r.nextInt(i + 1)).mapToObj(n -> r.nextBoolean() ? "" : String.valueOf(n)).toList(); List<String> resultSpliterator = StreamEx.of(input).collapse((str1, str2) -> str1.isEmpty() && str2 .isEmpty()).toList(); List<String> resultSpliteratorParallel = StreamEx.of(input).parallel().collapse((str1, str2) -> str1 .isEmpty() && str2.isEmpty()).toList(); List<String> expected = new ArrayList<>(); boolean lastSpace = false; for (String str : input) { if (str.isEmpty()) { if (!lastSpace) { expected.add(str); } lastSpace = true; } else { expected.add(str); lastSpace = false; } } assertEquals(expected, resultSpliterator); assertEquals(expected, resultSpliteratorParallel); })); } static class Interval { final int from, to; public Interval(int from) { this(from, from); } public Interval(int from, int to) { this.from = from; this.to = to; } public Interval merge(Interval other) { return new Interval(this.from, other.to); } public boolean adjacent(Interval other) { return other.from == this.to + 1; } @Override public String toString() { return from == to ? "{" + from + "}" : "[" + from + ".." + to + "]"; } } @Test public void testCollapseIntervals() { withRandom(r -> repeat(100, i -> { int size = r.nextInt(i * 5 + 1); int[] input = IntStreamEx.of(r, size, 0, size * 3 / 2 + 2).toArray(); String result = IntStreamEx.of(input).sorted().boxed().distinct().map(Interval::new).collapse( Interval::adjacent, Interval::merge).joining(" & "); String resultIntervalMap = IntStreamEx.of(input).sorted().boxed().distinct().intervalMap((a, b) -> b - a == 1, Interval::new).joining(" & "); String resultIntervalMapParallel = IntStreamEx.of(input).sorted().boxed().distinct().intervalMap((a, b) -> b - a == 1, Interval::new).parallel().joining(" & "); String resultParallel = IntStreamEx.of(input).parallel().sorted().boxed().distinct().map(Interval::new) .collapse(Interval::adjacent, Interval::merge).joining(" & "); String resultParallel2 = IntStreamEx.of(input).sorted().boxed().distinct().map(Interval::new).collapse( Interval::adjacent, Interval::merge).parallel().joining(" & "); String resultCollector = IntStreamEx.of(input).sorted().boxed().distinct().map(Interval::new).collapse( Interval::adjacent, Collectors.reducing(Interval::merge)).map(Optional::get).parallel().joining( " & "); int[] sorted = Arrays.copyOf(input, input.length); Arrays.sort(sorted); List<String> expected = new ArrayList<>(); Interval last = null; for (int num : sorted) { if (last != null) { if (last.to == num) continue; if (last.to == num - 1) { last = new Interval(last.from, num); continue; } expected.add(last.toString()); } last = new Interval(num); } if (last != null) expected.add(last.toString()); String expectedStr = String.join(" & ", expected); assertEquals(expectedStr, result); assertEquals(expectedStr, resultParallel); assertEquals(expectedStr, resultParallel2); assertEquals(expectedStr, resultIntervalMap); assertEquals(expectedStr, resultIntervalMapParallel); assertEquals(expectedStr, resultCollector); })); } @Test public void testCollapseDistinct() { withRandom(r -> repeat(100, i -> { int size = r.nextInt(i * 5 - 4); List<Integer> input = IntStreamEx.of(r, size, 0, size * 3 / 2 + 2).boxed().sorted().toList(); List<Integer> distinct = StreamEx.of(input).collapse(Integer::equals).toList(); List<Integer> distinctCollector = StreamEx.of(input).collapse(Integer::equals, MoreCollectors.first()) .map(Optional::get).toList(); List<Integer> distinctParallel = StreamEx.of(input).parallel().collapse(Integer::equals).toList(); List<Integer> distinctCollectorParallel = StreamEx.of(input).parallel().collapse(Integer::equals, MoreCollectors.first()).map(Optional::get).toList(); List<Integer> expected = input.stream().distinct().collect(Collectors.toList()); assertEquals(expected, distinct); assertEquals(expected, distinctParallel); assertEquals(expected, distinctCollector); assertEquals(expected, distinctCollectorParallel); })); } @Test public void testCollapsePairMap() { int[] input = { 0, 0, 1, 1, 1, 1, 4, 6, 6, 3, 3, 10 }; List<Integer> expected = IntStreamEx.of(input).pairMap((a, b) -> b - a).without(0).boxed().toList(); streamEx(() -> IntStreamEx.of(input).boxed(), supplier -> assertEquals(expected, supplier.get().collapse( Integer::equals).pairMap((a, b) -> b - a).toList())); } static StreamEx<String> sentences(StreamEx<String> source) { return source.flatMap(Pattern.compile("(?<=\\.)")::splitAsStream).collapse((a, b) -> !a.endsWith("."), (a, b) -> a + ' ' + b).map(String::trim); } @Test public void testStreamOfSentences() { List<String> lines = asList("This is the", "first sentence. This is the", "second sentence. Third sentence. Fourth", "sentence. Fifth sentence.", "The last"); streamEx(lines::stream, supplier -> assertEquals(asList("This is the first sentence.", "This is the second sentence.", "Third sentence.", "Fourth sentence.", "Fifth sentence.", "The last"), sentences(supplier.get()).toList())); } @Test public void testCollapseCollector() { List<String> input = asList("aaa", "bb", "baz", "bar", "foo", "fee", "abc"); streamEx(input::stream, supplier -> assertEquals(asList("aaa", "bb:baz:bar", "foo:fee", "abc"), supplier.get() .collapse((a, b) -> a.charAt(0) == b.charAt(0), Collectors.joining(":")).toList())); } @Test public void testLongestSeries() { List<Integer> input = asList(1, 2, 2, 3, 3, 2, 2, 2, 3, 4, 4, 4, 4, 4, 2); streamEx(input::stream, supplier -> assertEquals(5L, (long) supplier.get().collapse(Object::equals, Collectors .counting()).maxBy(Function.identity()).get())); } @Test public void testGroupRuns() { List<String> input = asList("aaa", "bb", "baz", "bar", "foo", "fee", "abc"); List<List<String>> expected = asList(asList("aaa"), asList("bb", "baz", "bar"), asList("foo", "fee"), asList( "abc")); streamEx(input::stream, supplier -> { assertEquals(expected, supplier.get().groupRuns((a, b) -> a.charAt(0) == b.charAt(0)).toList()); assertEquals(expected, supplier.get().collapse((a, b) -> a.charAt(0) == b.charAt(0), Collectors.toList()) .toList()); }); } @Test public void testGroupRunsRandom() { withRandom(r -> { List<Integer> input = IntStreamEx.of(r, 1000, 1, 100).sorted().boxed().toList(); List<List<Integer>> res1 = StreamEx.of(input).groupRuns(Integer::equals).toList(); List<List<Integer>> res1p = StreamEx.of(input).parallel().groupRuns(Integer::equals).toList(); List<List<Integer>> expected = new ArrayList<>(); List<Integer> last = null; for (Integer num : input) { if (last != null) { if (last.get(last.size() - 1).equals(num)) { last.add(num); continue; } expected.add(last); } last = new ArrayList<>(); last.add(num); } if (last != null) expected.add(last); assertEquals(expected, res1); assertEquals(expected, res1p); }); } @Test public void testGroupRunsSeparated() { streamEx(asList("a", "b", null, "c", null, "d", "e")::stream, supplier -> assertEquals(asList(asList("a", "b"), asList("c"), asList("d", "e")), supplier.get().groupRuns((a, b) -> a != null && b != null).remove( list -> list.get(0) == null).toList())); } @Test public void testGroupRunsByStart() { List<String> input = asList("str1", "str2", "START: str3", "str4", "START: str5", "START: str6", "START: str7", "str8", "str9"); Pattern start = Pattern.compile("^START:"); streamEx(input::stream, supplier -> assertEquals(asList(asList("str1", "str2"), asList("START: str3", "str4"), asList("START: str5"), asList("START: str6"), asList("START: str7", "str8", "str9")), supplier.get() .groupRuns((a, b) -> !start.matcher(b).find()).toList())); } private String format(StreamEx<Integer> ints) { return ints.distinct().sorted().<String> intervalMap((i, j) -> j == i + 1, (i, j) -> j.equals(i) ? i.toString() : j == i + 1 ? i + "," + j : i + ".." + j).joining(","); } private String formatNaive(int[] input) { StringBuilder msg = new StringBuilder(); int[] data = IntStreamEx.of(input).sorted().distinct().toArray(); int endNum; for (int i = 0; i < data.length; i++) { endNum = -1; for (int j = i + 1; j < data.length && (data[j] - data[j - 1] == 1); j++) endNum = j; if (msg.length() > 0) msg.append(','); msg.append(data[i]); if (endNum != -1 && (endNum - i) > 1) { msg.append("..").append(data[endNum]); i = endNum; } } return msg.toString(); } @Test public void testIntervalMapString() { int[] input = { 1, 5, 2, 10, 8, 11, 7, 15, 6, 5 }; String expected = formatNaive(input); assertEquals(expected, format(IntStreamEx.of(input).boxed())); for (int i = 0; i < 100; i++) assertEquals(expected, format(IntStreamEx.of(input).boxed().parallel())); input = IntStreamEx.range(3, 100).prepend(1).toArray(); assertEquals("1,3..99", format(IntStreamEx.of(input).boxed())); for (int i = 0; i < 100; i++) assertEquals("1,3..99", format(IntStreamEx.of(input).boxed().parallel())); input = IntStreamEx.of(new Random(1), 1000, 0, 2000).toArray(); expected = formatNaive(input); assertEquals(expected, format(IntStreamEx.of(input).boxed())); assertEquals(expected, format(IntStreamEx.of(input).boxed().parallel())); } @Test public void testRunLenghts() { Integer[] input = { 1, 2, 2, 4, 2, null, null, 1, 1, 1, null, null }; streamEx(() -> StreamEx.of(input), s -> { assertEquals("1: 1, 2: 2, 4: 1, 2: 1, null: 2, 1: 3, null: 2", s.get().runLengths().join(": ").joining( ", ")); assertEquals("1=1, 2=2, 4=1, 2=1, null=2, 1=3", s.get().runLengths().distinct().map(String::valueOf) .joining(", ")); }); Entry<Integer, Long> entry = StreamEx.of(input).runLengths().findFirst().get(); // Test qeuals contract for custom entry assertNotEquals(entry, new Object()); assertNotEquals(new Object(), entry); assertEquals(entry, new AbstractMap.SimpleImmutableEntry<>(1, 1L)); } @Test(expected = UnsupportedOperationException.class) public void testRunLengthsModify() { StreamEx.of("1", "1", "1").runLengths().forEach(e -> e.setValue(5L)); } @Test public void testRunLengthsSorted() { withRandom(r -> { int[] input = IntStreamEx.of(r, 1000, 1, 20).sorted().toArray(); Map<Integer, Long> expected = new HashMap<>(); long len = 1; for (int i = 0; i < input.length - 1; i++) { if (input[i] == input[i + 1]) { len++; } else { expected.put(input[i], len); len = 1; } } expected.put(input[input.length - 1], len); assertEquals(expected, IntStreamEx.of(input).sorted().boxed().runLengths().toMap()); assertEquals(expected, IntStreamEx.of(input).parallel().sorted().boxed().runLengths().toMap()); }); } /* * Returns longest input stream segment for which the predicate holds (like * the corresponding Scala method) */ private long segmentLength(IntStreamEx source, IntPredicate predicate) { return source.mapToObj(predicate::test).runLengths().removeKeys(Boolean.FALSE::equals).mapToLong( Entry::getValue).max().orElse(0); } @Test public void testSegmentLength() { Consumer<int[]> test = input -> { // get maximal count of consecutive positive numbers long res = segmentLength(IntStreamEx.of(input), x -> x > 0); long resParallel = segmentLength(IntStreamEx.of(input).parallel(), x -> x > 0); long expected = 0; long cur = input[0] > 0 ? 1 : 0; for (int i = 0; i < input.length - 1; i++) { if (input[i] > 0 && input[i + 1] > 0) cur++; else { if (cur > expected) expected = cur; cur = 1; } } if (cur > expected) expected = cur; assertEquals(expected, res); assertEquals(expected, resParallel); }; withRandom(r -> repeat(100, n -> test.accept(IntStreamEx.of(r, 1000, -10, 100).toArray()))); test.accept(new int[] { 1, 2, 3, -1 }); test.accept(new int[] { -1, 1, 2, -1, 1, 2, 3 }); } private static final class SeqList extends AbstractList<Integer> { final int size; SeqList(int size) { this.size = size; } @Override public Integer get(int index) { return index; } @Override public int size() { return size; } } @Test public void testSubLists() { List<Integer> input = IntStreamEx.range(12).boxed().toList(); assertEquals("[0, 1, 2, 3, 4]-[5, 6, 7, 8, 9]-[10, 11]", StreamEx.ofSubLists(input, 5).joining("-")); assertEquals("[0, 1, 2, 3]-[4, 5, 6, 7]-[8, 9, 10, 11]", StreamEx.ofSubLists(input, 4).joining("-")); assertEquals("[0]-[1]-[2]-[3]-[4]-[5]-[6]-[7]-[8]-[9]-[10]-[11]", StreamEx.ofSubLists(input, 1).joining("-")); assertEquals("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", StreamEx.ofSubLists(input, 12).joining("-")); assertEquals("[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", StreamEx.ofSubLists(input, Integer.MAX_VALUE).joining( "-")); assertEquals("", StreamEx.ofSubLists(Collections.emptyList(), 1).joining("-")); assertEquals("", StreamEx.ofSubLists(Collections.emptyList(), Integer.MAX_VALUE).joining("-")); List<Integer> myList = new SeqList(Integer.MAX_VALUE - 2); assertEquals(1, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 1).count()); assertEquals(Integer.MAX_VALUE - 2, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 1).findFirst().get() .size()); assertEquals(1, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 2).count()); assertEquals(1, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 3).skip(1).findFirst().get().size()); } @Test public void testSubListsStep() { List<Integer> input = IntStreamEx.range(12).boxed().toList(); assertEquals("[0, 1, 2, 3, 4]", StreamEx.ofSubLists(input, 5, Integer.MAX_VALUE).joining("-")); assertEquals("[0, 1, 2, 3, 4]", StreamEx.ofSubLists(input, 5, 12).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[11]", StreamEx.ofSubLists(input, 5, 11).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[9, 10, 11]", StreamEx.ofSubLists(input, 5, 9).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[8, 9, 10, 11]", StreamEx.ofSubLists(input, 5, 8).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[7, 8, 9, 10, 11]", StreamEx.ofSubLists(input, 5, 7).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[6, 7, 8, 9, 10]", StreamEx.ofSubLists(input, 5, 6).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[4, 5, 6, 7, 8]-[8, 9, 10, 11]", StreamEx.ofSubLists(input, 5, 4).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[3, 4, 5, 6, 7]-[6, 7, 8, 9, 10]-[9, 10, 11]", StreamEx.ofSubLists(input, 5, 3) .joining("-")); assertEquals("[0, 1, 2, 3, 4]-[2, 3, 4, 5, 6]-[4, 5, 6, 7, 8]-[6, 7, 8, 9, 10]-[8, 9, 10, 11]", StreamEx .ofSubLists(input, 5, 2).joining("-")); assertEquals("[0, 1, 2, 3, 4]-[1, 2, 3, 4, 5]-[2, 3, 4, 5, 6]-[3, 4, 5, 6, 7]-" + "[4, 5, 6, 7, 8]-[5, 6, 7, 8, 9]-[6, 7, 8, 9, 10]-[7, 8, 9, 10, 11]", StreamEx.ofSubLists(input, 5, 1) .joining("-")); List<Integer> myList = new SeqList(Integer.MAX_VALUE - 2); assertEquals(1, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 1, 1).count()); assertEquals("[0]", StreamEx.ofSubLists(myList, 1, Integer.MAX_VALUE - 1).joining()); assertEquals("[0]", StreamEx.ofSubLists(myList, 1, Integer.MAX_VALUE - 2).joining()); assertEquals("[0][2147483644]", StreamEx.ofSubLists(myList, 1, Integer.MAX_VALUE - 3).joining()); assertEquals("[0, 1]", StreamEx.ofSubLists(myList, 2, Integer.MAX_VALUE - 1).joining()); assertEquals("[0, 1]", StreamEx.ofSubLists(myList, 2, Integer.MAX_VALUE - 2).joining()); assertEquals("[0, 1][2147483644]", StreamEx.ofSubLists(myList, 2, Integer.MAX_VALUE - 3).joining()); assertEquals(Integer.MAX_VALUE - 2, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 1, 1).findFirst().get() .size()); assertEquals(1, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 2, 1).count()); assertEquals(998, StreamEx.ofSubLists(myList, Integer.MAX_VALUE - 3, Integer.MAX_VALUE - 1000).skip(1) .findFirst().get().size()); } @Test(expected = IllegalArgumentException.class) public void testSubListsArg() { StreamEx.ofSubLists(Collections.emptyList(), 0); } @Test(expected = IllegalArgumentException.class) public void testSubListsStepArg() { StreamEx.ofSubLists(Collections.emptyList(), 1, 0); } @Test public void testTakeWhile() { streamEx(asList("aaa", "b", "cccc")::stream, s -> { assertEquals(asList("aaa"), s.get().takeWhile(x -> x.length() > 1).toList()); assertEquals(asList("aaa"), s.get().sorted().takeWhile(x -> x.length() > 1).toList()); assertEquals(asList("aaa", "b", "cccc"), s.get().takeWhile(x -> x.length() > 0).toList()); assertEquals(Collections.emptyList(), s.get().takeWhile(x -> x.length() > 5).toList()); }); } @Test public void testTakeWhileInclusive() { streamEx(asList("aaa", "b", "cccc")::stream, s -> { assertEquals(asList("aaa", "b"), s.get().takeWhileInclusive(x -> x.length() > 1).toList()); assertEquals(asList("aaa", "b", "cccc"), s.get().takeWhileInclusive(x -> x.length() > 0).toList()); assertEquals(asList("aaa"), s.get().takeWhileInclusive(x -> x.length() > 5).toList()); }); } @Test public void testDropWhile() { streamEx(asList("aaa", "b", "cccc")::stream, s -> { assertEquals(asList("b", "cccc"), s.get().dropWhile(x -> x.length() > 1).toList()); assertEquals(asList(), s.get().dropWhile(x -> x.length() > 0).toList()); assertEquals(asList("aaa", "b", "cccc"), s.get().dropWhile(x -> x.length() > 5).toList()); // Saving to Optional is necessary as javac <8u40 fails to compile // this without intermediate variable Optional<String> opt1 = s.get().dropWhile(x -> x.length() > 1).findFirst(); assertEquals(Optional.of("b"), opt1); Optional<String> opt0 = s.get().dropWhile(x -> x.length() > 0).findFirst(); assertEquals(Optional.empty(), opt0); Optional<String> opt5 = s.get().dropWhile(x -> x.length() > 5).findFirst(); assertEquals(Optional.of("aaa"), opt5); }); // Test that in JDK9 operation is propagated to JDK dropWhile method. boolean hasDropWhile = true; try { Stream.class.getDeclaredMethod("dropWhile", Predicate.class); } catch (NoSuchMethodException e) { hasDropWhile = false; } Spliterator<String> spliterator = StreamEx.of("aaa", "b", "cccc").dropWhile(x -> x.length() > 1).spliterator(); assertEquals(hasDropWhile, !spliterator.getClass().getSimpleName().equals("TDOfRef")); } @Test public void testTakeDropUnordered() { repeat(10, n -> withRandom(rnd -> { List<Boolean> data = IntStreamEx.of(rnd, n*100, 0, rnd.nextInt(10)+2).mapToObj(x -> x != 0).toList(); List<Boolean> sorted = StreamEx.of(data).sorted().toList(); streamEx(() -> data.stream().unordered(), s -> { assertFalse(StreamEx.of(s.get().takeWhile(b -> b).toList()).has(false)); assertEquals(1L, StreamEx.of(s.get().takeWhileInclusive(b -> b).toList()).without(true).count()); assertEquals(0L, s.get().dropWhile(b -> true).count()); assertEquals(0L, s.get().takeWhile(b -> false).count()); assertEquals(1L, s.get().takeWhileInclusive(b -> false).count()); List<Boolean> dropNone = s.get().dropWhile(b -> false).sorted().toList(); assertEquals(sorted, dropNone); List<Boolean> takeAll = s.get().takeWhileInclusive(b -> true).sorted().toList(); assertEquals(sorted, takeAll); }); })); } @Test public void testOfPairs() { withRandom(r -> { Point[] pts = StreamEx.generate(() -> new Point(r.nextDouble(), r.nextDouble())).limit(100).toArray( Point[]::new); double expected = StreamEx.of(pts).cross(pts).mapKeyValue(Point::distance).mapToDouble(Double::doubleValue) .max().getAsDouble(); double[] allDist = IntStreamEx.ofIndices(pts).flatMapToDouble(i1 -> StreamEx.of(pts, i1 + 1, pts.length) .mapToDouble(pt -> pt.distance(pts[i1]))).toArray(); streamEx(() -> StreamEx.ofPairs(pts, Point::distance), supplier -> { assertEquals(expected, supplier.get().mapToDouble(Double::doubleValue).max().getAsDouble(), 0.0); assertArrayEquals(allDist, supplier.get().mapToDouble(Double::doubleValue).toArray(), 0.0); }); }); } @Test public void testToFlatCollection() { List<List<String>> strings = IntStreamEx.range(100).mapToObj(String::valueOf).groupRuns((a, b) -> a.charAt( 0) == b.charAt(0)).toList(); Set<String> expected = IntStreamEx.range(100).mapToObj(String::valueOf).toSet(); List<String> expectedList = IntStreamEx.range(100).mapToObj(String::valueOf).toList(); streamEx(strings::stream, supplier -> { assertEquals(expected, supplier.get().toFlatCollection(x -> x, HashSet::new)); assertEquals(expectedList, supplier.get().toFlatList(x -> x)); }); } @Test public void testCartesian() { List<List<Integer>> expected = IntStreamEx.range(32).mapToObj(i -> IntStreamEx.range(5).mapToObj(n -> (i >> (4 - n)) & 1).toList()).toList(); streamEx(() -> StreamEx.cartesianPower(5, asList(0, 1)), supplier -> assertEquals(expected, supplier.get() .toList())); List<List<Integer>> input2 = asList(asList(1, 2, 3), asList(), asList(4, 5, 6)); streamEx(() -> StreamEx.cartesianProduct(input2), supplier -> assertFalse(supplier.get().findAny() .isPresent())); List<List<Integer>> input3 = asList(asList(1, 2), asList(3), asList(4, 5)); streamEx(() -> StreamEx.cartesianProduct(input3), supplier -> assertEquals( "[1, 3, 4],[1, 3, 5],[2, 3, 4],[2, 3, 5]", supplier.get().joining(","))); Set<Integer> input4 = IntStreamEx.range(10).boxed().toCollection(TreeSet::new); streamEx(() -> StreamEx.cartesianPower(3, input4), supplier -> assertEquals(IntStreamEx.range(1000).boxed() .toList(), supplier.get().map(list -> list.get(0) * 100 + list.get(1) * 10 + list.get(2)).toList())); assertEquals(asList(Collections.emptyList()), StreamEx.cartesianProduct(Collections.emptyList()).toList()); assertEquals(asList(Collections.emptyList()), StreamEx.cartesianPower(0, asList(1, 2, 3)).toList()); } @Test public void testCartesianReduce() { List<String> expected = IntStreamEx.range(32).mapToObj(i -> IntStreamEx.range(5).mapToObj(n -> (i >> (4 - n)) & 1).joining()).toList(); streamEx(() -> StreamEx.cartesianPower(5, asList(0, 1), "", (a, b) -> a + b), supplier -> assertEquals(expected, supplier.get().toList())); List<List<Integer>> input2 = asList(asList(1, 2, 3), asList(), asList(4, 5, 6)); streamEx(() -> StreamEx.cartesianProduct(input2, "", (a, b) -> a + b), supplier -> assertFalse(supplier.get() .findAny().isPresent())); List<List<Integer>> input3 = asList(asList(1, 2), asList(3), asList(4, 5)); streamEx(() -> StreamEx.cartesianProduct(input3, "", (a, b) -> a + b), supplier -> assertEquals( "134,135,234,235", supplier.get().joining(","))); assertEquals(asList(""), StreamEx.cartesianProduct(Collections.<List<String>> emptyList(), "", String::concat) .toList()); assertEquals(asList(""), StreamEx.cartesianPower(0, asList(1, 2, 3), "", (a, b) -> a + b).toList()); } @Test public void testDistinct() { List<String> input = asList("str", "a", "foo", "", "bbbb", null, "abcd", "s"); streamEx(input::stream, supplier -> { assertEquals(input, supplier.get().distinct(x -> x).toList()); assertEquals(asList("str", "a", "", "bbbb"), supplier.get().distinct(x -> x == null ? 0 : x.length()) .toList()); }); } @Test public void testIndexOf() { List<Integer> input = IntStreamEx.range(100).append(IntStreamEx.range(100)).boxed().toList(); AtomicInteger counter = new AtomicInteger(); assertEquals(10, StreamEx.of(input).peek(t -> counter.incrementAndGet()).indexOf(10).getAsLong()); assertEquals(11, counter.get()); for (int i = 0; i < 100; i++) { assertEquals(99, StreamEx.of(input).parallel().prepend().peek(t -> counter.incrementAndGet()).indexOf(99) .getAsLong()); } streamEx(input::stream, supplier -> { for (int i : new int[] { 0, 1, 10, 50, 78, 99 }) { assertEquals("#" + i, i, supplier.get().peek(t -> counter.incrementAndGet()).indexOf(x -> x == i) .getAsLong()); } assertFalse(supplier.get().indexOf(""::equals).isPresent()); }); } @Test public void testIndexOfSimple() { List<Integer> input = IntStreamEx.range(10).boxed().toList(); for (int i = 0; i < 100; i++) { assertEquals(9, StreamEx.of(input).parallel().indexOf(9).getAsLong()); } } @Test public void testMapFirstLast() { streamEx(() -> StreamEx.of(0, 343, 999), s -> assertEquals(asList(2, 343, 997), s.get().mapFirst(x -> x + 2) .mapLast(x -> x - 2).toList())); streamEx(() -> IntStreamEx.range(1000).boxed(), s -> { assertEquals(asList(2, 343, 997), s.get().filter(x -> x == 0 || x == 343 || x == 999).mapFirst(x -> x + 2) .mapLast(x -> x - 2).toList()); assertEquals(asList(4, 343, 997), s.get().filter(x -> x == 0 || x == 343 || x == 999).mapFirst(x -> x + 2) .mapFirst(x -> x + 2).mapLast(x -> x - 2).toList()); }); Supplier<Stream<Integer>> base = () -> IntStreamEx.rangeClosed(49, 0, -1).boxed().foldLeft(StreamEx.of(0), ( stream, i) -> stream.prepend(i).mapFirst(x -> x + 2)); streamEx(base, s -> assertEquals(IntStreamEx.range(2, 52).boxed().append(0).toList(), s.get().toList())); base = () -> IntStreamEx.range(50).boxed().foldLeft(StreamEx.of(0), (stream, i) -> stream.append(i).mapLast( x -> x + 2)); streamEx(base, s -> assertEquals(IntStreamEx.range(2, 52).boxed().prepend(0).toList(), s.get().toList())); streamEx(asList("red", "green", "blue", "orange")::stream, s -> assertEquals("red, green, blue, or orange", s .get().mapLast("or "::concat).joining(", "))); } @Test public void testMapFirstOrElse() { streamEx(() -> StreamEx.split("testString", ""), s -> assertEquals("Teststring", s.get().mapFirstOrElse( String::toUpperCase, String::toLowerCase).joining())); } @Test public void testMapLastOrElse() { streamEx(asList("red", "green", "blue", "orange")::stream, s -> assertEquals("red, green, blue, or orange!", s .get().mapLastOrElse(str -> str + ", ", str -> "or " + str + "!").joining())); streamEx(asList("red", "green", "blue", "orange")::stream, s -> assertEquals( "|- red\n|- green\n|- blue\n\\- orange", s.get().mapLastOrElse("|- "::concat, "\\- "::concat).joining( "\n"))); } @Test public void testPeekFirst() { List<String> input = asList("A", "B", "C", "D"); streamEx(input::stream, s -> { AtomicReference<String> firstElement = new AtomicReference<>(); assertEquals(asList("B", "C", "D"), s.get().peekFirst(firstElement::set).skip(1).toList()); assertEquals("A", firstElement.get()); assertEquals(asList("B", "C", "D"), s.get().skip(1).peekFirst(firstElement::set).toList()); assertEquals("B", firstElement.get()); firstElement.set(null); assertEquals(asList(), s.get().skip(4).peekFirst(firstElement::set).toList()); assertNull(firstElement.get()); }); } @Test public void testPeekLast() { List<String> input = asList("A", "B", "C", "D"); AtomicReference<String> lastElement = new AtomicReference<>(); assertEquals(asList("A", "B", "C"), StreamEx.of(input).peekLast(lastElement::set).limit(3).toList()); assertNull(lastElement.get()); assertEquals(input, StreamEx.of(input).peekLast(lastElement::set).limit(4).toList()); assertEquals("D", lastElement.get()); assertEquals(asList("A", "B", "C"), StreamEx.of(input).limit(3).peekLast(lastElement::set).toList()); assertEquals("C", lastElement.get()); lastElement.set(null); assertEquals(2L, StreamEx.of(input).peekLast(lastElement::set).indexOf("C").getAsLong()); assertNull(lastElement.get()); assertEquals(3L, StreamEx.of(input).peekLast(lastElement::set).indexOf("D").getAsLong()); assertEquals("D", lastElement.get()); } @Test public void testSplit() { assertFalse(StreamEx.split("str", "abcd").spliterator().getClass().getSimpleName().endsWith( "IteratorSpliterator")); assertFalse(StreamEx.split("str", Pattern.compile("abcd")).spliterator().getClass().getSimpleName().endsWith( "IteratorSpliterator")); streamEx(() -> StreamEx.split("", "abcd"), s -> assertEquals(1, s.get().count())); streamEx(() -> StreamEx.split("", Pattern.compile("abcd")), s -> assertEquals(1, s.get().count())); streamEx(() -> StreamEx.split("ab.cd...", '.'), s -> assertEquals("ab|cd", s.get().joining("|"))); streamEx(() -> StreamEx.split("ab.cd...", "."), s -> assertEquals(0, s.get().count())); streamEx(() -> StreamEx.split("ab.cd...", "\\."), s -> assertEquals("ab|cd", s.get().joining("|"))); streamEx(() -> StreamEx.split("ab.cd...", "cd"), s -> assertEquals("ab.|...", s.get().joining("|"))); streamEx(() -> StreamEx.split("ab.cd...", "\\w"), s -> assertEquals("||.||...", s.get().joining("|"))); streamEx(() -> StreamEx.split("ab.cd...", "\\W"), s -> assertEquals("ab|cd", s.get().joining("|"))); streamEx(() -> StreamEx.split("ab|cd|e", "\\|"), s -> assertEquals("ab,cd,e", s.get().joining(","))); } @Test public void testSplitChar() { streamEx(() -> StreamEx.split("abcd,e,f,gh,,,i,j,kl,,,,,,", ','), s -> assertEquals("abcd|e|f|gh|||i|j|kl", s .get().joining("|"))); streamEx(() -> StreamEx.split("abcd,e,f,gh,,,i,j,kl,,,,,,x", ','), s -> assertEquals( "abcd|e|f|gh|||i|j|kl||||||x", s.get().joining("|"))); streamEx(() -> StreamEx.split("abcd", ','), s -> assertEquals("abcd", s.get().joining("|"))); streamEx(() -> StreamEx.split("", ','), s -> assertEquals(asList(""), s.get().toList())); streamEx(() -> StreamEx.split(",,,,,,,,,", ','), s -> assertEquals(0, s.get().count())); withRandom(r -> repeat(10, iter -> { StringBuilder source = new StringBuilder(IntStreamEx.of(r, 0, 3).limit(r.nextInt(10000)).elements( new int[] { ',', 'a', 'b' }).charsToString()); String[] expected = source.toString().split(","); String[] expectedFull = source.toString().split(",", -1); streamEx(() -> StreamEx.split(source, ','), s -> assertArrayEquals(expected, s.get().toArray( String[]::new))); streamEx(() -> StreamEx.split(source, ',', false), s -> assertArrayEquals(expectedFull, s.get().toArray( String[]::new))); })); } @Test public void testWithFirst() { repeat(10, i -> { streamEx(() -> StreamEx.of(0, 2, 4), s -> assertEquals(asList("0|0", "0|1", "0|2", "0|3", "0|4", "0|5"), s .get().flatMap(x -> Stream.of(x, x + 1)).withFirst().mapKeyValue((a, b) -> a + "|" + b).toList())); // Check exception-friendliness: short-circuiting collectors use Exceptions for control flow streamEx(() -> IntStreamEx.range(100).boxed(), s -> { assertEquals("0|0, 0|1, 0|2, ...", s.get().withFirst((a, b) -> a + "|" + b).collect(Joining.with(", ") .maxChars(18))); assertEquals(asList(), s.get().withFirst((a, b) -> a + "|" + b).collect(MoreCollectors.head(0))); }); streamEx(() -> StreamEx.of("a", "b", "c", "d"), s -> assertEquals(Collections.singletonMap("a", asList("a", "b", "c", "d")), s.get().withFirst().grouping())); streamEx(() -> StreamEx.of("a", "b", "c", "d"), s -> assertEquals(asList("aa", "ab", "ac", "ad"), s.get() .withFirst(String::concat).toList())); // Header mapping String input = "name,type,value\nID,int,5\nSurname,string,Smith\nGiven name,string,John"; List<Map<String, String>> expected = asList(EntryStream.of("name", "ID", "type", "int", "value", "5") .toMap(), EntryStream.of("name", "Surname", "type", "string", "value", "Smith").toMap(), EntryStream .of("name", "Given name", "type", "string", "value", "John").toMap()); streamEx(() -> StreamEx.ofLines(new StringReader(input)), s -> { assertEquals(expected, s.get().map(str -> str.split(",")).withFirst().skip(1).mapKeyValue((header, row) -> EntryStream.zip(header, row).toMap()).toList()); assertEquals(expected, s.get().map(str -> str.split(",")).withFirst((header, row) -> EntryStream.zip( header, row).toMap()).skip(1).toList()); }); }); Map<Integer, List<Integer>> expected = Collections.singletonMap(0, IntStreamEx.range(0, 10000).boxed() .toList()); streamEx(() -> IntStreamEx.range(10000).boxed(), s -> assertEquals(expected, s.get().withFirst().grouping())); streamEx(() -> StreamEx.of(5, 10, 13, 12, 11), s -> assertEquals(asList("5+0", "5+5", "5+8", "5+7", "5+6"), s .get().withFirst((a, b) -> a + "+" + (b - a)).toList())); } @Test public void testZipWith() { List<String> input = asList("John", "Mary", "Jane", "Jimmy"); Spliterator<String> spliterator = StreamEx.of(input).zipWith(IntStreamEx.range(1, Integer.MAX_VALUE).boxed(), ( name, idx) -> idx + ". " + name).spliterator(); assertEquals(4, spliterator.getExactSizeIfKnown()); List<String> expected = asList("1. John", "2. Mary", "3. Jane", "4. Jimmy"); streamEx(input::stream, s -> assertEquals(expected, s.get().zipWith(IntStream.range(1, Integer.MAX_VALUE) .boxed(), (name, idx) -> idx + ". " + name).toList())); streamEx(input::stream, s -> assertEquals(expected, s.get().zipWith(IntStream.range(1, Integer.MAX_VALUE) .boxed()).mapKeyValue((name, idx) -> idx + ". " + name).toList())); streamEx(() -> IntStream.range(1, Integer.MAX_VALUE).boxed(), s -> assertEquals(expected, s.get().zipWith(input .stream(), (idx, name) -> idx + ". " + name).toList())); } // Like Stream.generate(supplier) public static <T> StreamEx<T> generate(Supplier<T> supplier) { return StreamEx.produce(action -> { action.accept(supplier.get()); return true; }); } // Adapt spliterator to produce public static <T> StreamEx<T> fromSpliterator(Spliterator<T> spltr) { return StreamEx.produce((Predicate<Consumer<? super T>>) spltr::tryAdvance); } // Adapt iterator to produce public static <T> StreamEx<T> fromIterator(Iterator<T> iter) { return StreamEx.produce(action -> { if (!iter.hasNext()) return false; action.accept(iter.next()); return true; }); } // Stream of all matches of given matcher public static StreamEx<String> matches(Matcher m) { return StreamEx.produce(action -> { if (!m.find()) return false; action.accept(m.group()); return true; }); } public static <T> StreamEx<T> fromQueue(Queue<T> queue, T sentinel) { return StreamEx.produce(action -> { T next = queue.poll(); if (next == null || next.equals(sentinel)) return false; action.accept(next); return true; }); } @Test public void testProduce() { assertEquals(asList(4, 4, 4, 4, 4), generate(() -> 4).limit(5).toList()); assertEquals(asList("foo", "bar", "baz"), fromSpliterator(asList("foo", "bar", "baz").spliterator()).toList()); assertEquals(asList("foo", "bar", "baz"), fromIterator(asList("foo", "bar", "baz").iterator()).toList()); assertEquals(asList("123", "543", "111", "5432"), matches(Pattern.compile("\\d+").matcher("123 543,111:5432")) .toList()); Queue<String> queue = new ArrayDeque<>(asList("one", "two", "STOP", "three", "four", "five", "STOP", "STOP", "six")); assertEquals(asList("one", "two"), fromQueue(queue, "STOP").toList()); assertEquals(asList("three", "four", "five"), fromQueue(queue, "STOP").toList()); assertEquals(asList(), fromQueue(queue, "STOP").toList()); assertEquals(asList("six"), fromQueue(queue, "STOP").toList()); assertEquals(asList(), fromQueue(queue, "STOP").toList()); } @Test public void testPrefix() { List<String> input = asList("a", "b", "c", "d", "e"); streamEx(input::stream, s -> assertEquals(asList("a", "ab", "abc", "abcd", "abcde"), s.get().prefix( String::concat).toList())); streamEx(input::stream, s -> assertEquals(Optional.of("abcd"), s.get().prefix(String::concat).findFirst( str -> str.length() > 3))); streamEx(() -> StreamEx.constant("a", 5), s -> assertEquals(new HashSet<>(asList("a", "aa", "aaa", "aaaa", "aaaaa")), s.get().prefix(String::concat).toSet())); streamEx(() -> StreamEx.constant("a", 5), s -> assertEquals(Optional.of("aaaaa"), s.get().prefix(String::concat) .findFirst(str -> str.length() > 4))); streamEx(() -> StreamEx.constant(100L, 10000), s -> assertEquals(5000500000L, (long) s.get().prefix(Long::sum) .reduce(0L, Long::sum))); streamEx(() -> IntStreamEx.range(10000).boxed().unordered(), s -> assertEquals(49995000, s.get().prefix( Integer::sum).mapToInt(Integer::intValue).max().getAsInt())); } /** * Returns maximal stream value short-circuiting when stopValue is reached * * @param stream stream to process * @param comparator comparator to compare stream values * @param stopValue value to short-circuit at * @return optional describing maximal value or empty optional if input * stream is empty */ static <T> Optional<T> maxWithStop(StreamEx<T> stream, Comparator<T> comparator, T stopValue) { return stream.prefix(BinaryOperator.maxBy(comparator)).takeWhileInclusive(Predicate.isEqual(stopValue).negate()) .collect(MoreCollectors.last()); } @Test public void testMaxWithStop() { // Infinite stream, stop is reached assertEquals(Optional.of(1000), maxWithStop(IntStreamEx.of(new Random(1), 0, 1001).boxed(), Comparator .naturalOrder(), 1000)); // FInite stream, stop is not reached assertEquals(Optional.of(999), maxWithStop(IntStreamEx.of(new Random(1), 10000, 0, 1000).boxed(), Comparator .naturalOrder(), 1000)); } @Test public void testToImmutableList() { List<Integer> expected = asList(1, 2, 3); repeat(4, n -> streamEx(() -> IntStreamEx.range(4).atLeast(n).boxed(), s -> { List<Integer> list = s.get().toImmutableList(); assertEquals(expected.subList(n - 1, expected.size()), list); try { list.add(0); fail("added"); } catch (UnsupportedOperationException e) { // expected } try { list.set(0, 0); fail("set"); } catch (UnsupportedOperationException e) { // expected } })); } @Test public void testToImmutableSet() { List<Integer> expected = asList(1, 2, 3); repeat(4, n -> streamEx(() -> IntStreamEx.range(4).atLeast(n).boxed(), s -> { Set<Integer> set = s.get().toImmutableSet(); assertEquals(new HashSet<>(expected.subList(n - 1, expected.size())), set); try { set.add(-1); fail("added"); } catch (UnsupportedOperationException e) { // expected } })); } @Test public void testInto() { for (List<Number> list : asList(new ArrayList<Number>(), new LinkedList<Number>())) { List<Number> res = StreamEx.of(1, 2, 3, 4).filter(x -> x < 4).into(list); assertSame(list, res); assertEquals(asList(1, 2, 3), list); assertSame(list, StreamEx.of(4, 5, 6).into(list)); assertEquals(asList(1, 2, 3, 4, 5, 6), list); assertSame(list, StreamEx.of(7, 8, 9, 10).parallel().into(list)); assertEquals(asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), list); } // a kind of mock object Collection<String> c = new ArrayList<String>() { private static final long serialVersionUID = 1L; int size = Integer.MAX_VALUE - 10; @Override public boolean add(String e) { assertEquals("a", e); size++; return true; } @Override public int size() { return size; } }; assertSame(c, StreamEx.constant("a", 20).into(c)); //noinspection NumericOverflow assertEquals(Integer.MAX_VALUE + 10, c.size()); } @Test public void testFilterBy() { assertEquals(3, StreamEx.of("a", "bb", "c", "e", "ddd").filterBy(String::length, 1).count()); assertEquals(2, StreamEx.of("a", "bb", "c", "e", "ddd").filterBy(x -> x.length() > 1 ? null : x, null).count()); } @Test public void testRemoveBy() { assertEquals(2, StreamEx.of("a", "bb", "c", "e", "ddd").removeBy(String::length, 1).count()); assertEquals(3, StreamEx.of("a", "bb", "c", "e", "ddd").removeBy(x -> x.length() > 1 ? null : x, null).count()); } @Test public void testIntersperse() { List<String> expected = asList("a", "--", "b", "--", "c", "--", "d", "--", "e"); streamEx(asList("a", "b", "c", "d", "e")::stream, s -> assertEquals(expected, s.get().intersperse("--").toList())); assertEquals(Collections.emptyList(), StreamEx.empty().intersperse("xyz").toList()); } }