If you don't mind using a third-party library, Eclipse Collections has zipWithIndex and forEachWithIndex available for use across many types. Here's a set of solutions to this challenge for both JDK types and Eclipse Collections types using zipWithIndex.
String[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" }; ImmutableList<String> expected = Lists.immutable.with("Erik"); Predicate<Pair<String, Integer>> predicate = pair -> pair.getOne().length() <= pair.getTwo() + 1; // JDK Types List<String> strings1 = ArrayIterate.zipWithIndex(names) .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings1); List<String> list = Arrays.asList(names); List<String> strings2 = ListAdapter.adapt(list) .zipWithIndex() .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings2); // Eclipse Collections types MutableList<String> mutableNames = Lists.mutable.with(names); MutableList<String> strings3 = mutableNames.zipWithIndex() .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings3); ImmutableList<String> immutableNames = Lists.immutable.with(names); ImmutableList<String> strings4 = immutableNames.zipWithIndex() .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings4); MutableList<String> strings5 = mutableNames.asLazy() .zipWithIndex() .collectIf(predicate, Pair::getOne, Lists.mutable.empty()); Assert.assertEquals(expected, strings5);
Here's a solution using forEachWithIndex instead.
MutableList<String> mutableNames = Lists.mutable.with("Sam", "Pamela", "Dave", "Pascal", "Erik"); ImmutableList<String> expected = Lists.immutable.with("Erik"); List<String> actual = Lists.mutable.empty(); mutableNames.forEachWithIndex((name, index) -> { if (name.length() <= index + 1) actual.add(name); }); Assert.assertEquals(expected, actual);
If you change the lambdas to anonymous inner classes above, then all of these code examples will work in Java 5 - 7 as well.
Note: I am a committer for Eclipse Collections
intRange()? Haven't come accross this method in Java 8 till now.IntStream.rangeClosed(x, y).List<String> allCities = map.values().stream().flatMap(list -> list.stream()).collect(Collectors.toList());zipwas removed, along with experimental two-valued streams variously calledBiStreamorMapStream. The main problem is that to do this effectively Java really needs a structurally-typed pair (or tuple) type. Lacking one, it's easy to create a generic Pair or Tuple class -- it's been done many times -- but they all erase to the same type.