17

I am trying sequential search using Java 8 streams and lambda expressions. Here is my code

List<Integer> list = Arrays.asList(10, 6, 16, 46, 5, 16, 7);
int search = 16;
list.stream().filter(p -> p == search).forEachOrdered(e -> System.out.println(list.indexOf(e)));
Output: 2
        2

I know list.indexOf(e) always prints the index of the first occurrence. How do I print all the indexes?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
mallikarjun
  • 1,862
  • 5
  • 23
  • 47
  • I don't think you can do it with this kind of structure. Once you've filtered, you've lost the index information. If you did print indexes after this, you'd get indexes within the filtered list. – chiastic-security Oct 03 '14 at 12:38
  • 1
    Possible duplicate of http://stackoverflow.com/q/18552005/1407656 or http://stackoverflow.com/q/22793006/1407656 – toniedzwiedz Oct 03 '14 at 12:38
  • @Tom what is query in the given post. when i try this giving compilation error at query. – mallikarjun Oct 03 '14 at 12:49

2 Answers2

31

For a start, using Lambdas is not the solution to all problems... but, even then, as a for loop, you would write it:

List<Integer> results = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
    if (search == list.get(i).intValue()) {
        // found value at index i
        results.add(i);
    }
}

Now, there's nothing particularly wrong with that, but note that the critical aspect here is the index, not the value. The index is the input, and the output of the 'loop'.

As a stream::

List<Integer> list = Arrays.asList(10, 6, 16, 46, 5, 16, 7);
int search = 16;
int[] indices = IntStream.range(0, list.size())
                .filter(i -> list.get(i) == search)
                .toArray();
System.out.printf("Found %d at indices %s%n", search, Arrays.toString(indices));

Produces output:

Found 16 at indices [2, 5]
rolfl
  • 17,539
  • 7
  • 42
  • 76
  • Is there exra %n at the end of printf function, three subsitutes but two params was provided? – Whome Oct 03 '14 at 12:55
  • 4
    @Whome - the `%n` adds an OS specific line-terminator (a well-behaved `\n`). It does not need a matching substitution value. (See "Line Separator [in the documentation](http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html) ) – rolfl Oct 03 '14 at 12:58
1

To find the indexes of every value in a List as a Map, we can use an IntStream of indexes with Collectors.groupingBy.

import java.util.stream.Collectors;
import java.util.stream.IntStream;
//...
final Map<Integer, List<Integer>> indexMap = IntStream.range(0, list.size()).boxed()
        .collect(Collectors.groupingBy(list::get));
//{16=[2, 5], 5=[4], 6=[1], 7=[6], 10=[0], 46=[3]}
//Map of item value to List of indices at which it occurs in the original List

Demo

Now, if you want to get the list of indices for search, you can do so as follows:

System.out.println(indexMap.get(search));
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
Unmitigated
  • 76,500
  • 11
  • 62
  • 80