0

I have an array which I want to convert to Map such that the first element in the array is key and second element is value and so on.

I am trying something like below:

Arrays.asList("Tamilnadu", "chennai", "Karnataka", "Bengluru")
                .stream()
                .collect(HashMap::new,
                        (a, b) -> a.put(b, ""),//value should be next element in array
                        (a, b) -> a.putAll(b)
                );

My confusion is how to get next element in same collect iteration so that I could do a.put(b,nextElementToB).

Can someone help with this problem by using streams as I want to try functional programming for same? Is iterating going to be the only way of doing this?

Vinay Prajapati
  • 7,199
  • 9
  • 45
  • 86

3 Answers3

7

You can use an IntStream of the indices of the List:

Map<String,String> map = 
    IntStream.range(0,list.size()/2)
             .boxed()
             .collect(Collectors.toMap(i->list.get(2*i),i->list.get(2*i+1)));

This is assuming the List has an even number of elements.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • You cannot use a `Collector` with an `IntStream`. You need to insert a `.boxed()`. Or, since this looks very much like an *xy problem*, just use `Map map = Map.of("Tamilnadu", "chennai", "Karnataka", "Bengluru");`… – Holger Jun 25 '18 at 09:33
  • @Holger thanks. I missed that – Eran Jun 25 '18 at 09:34
3

You can use toMap method

public static Map toMap(Object[] array)

Converts the given array into a Map. Each element of the array must be either a Map.Entry or an Array, containing at least two elements, where the first element is used as key and the second as value.

This method can be used to initialize:

// Create a Map mapping colors. Map colorMap = ArrayUtils.toMap(new String[][] { {"RED", "#FF0000"}, {"GREEN", "#00FF00"}, {"BLUE", "#0000FF"}}); This method returns null for a null input array.

Parameters: array - an array whose elements are either a Map.Entry or an Array containing at least two elements, may be null

Returns: a Map that was created from the array

Throws: IllegalArgumentException - if one element of this Array is itself an Array containing less then two elements IllegalArgumentException - if the array contains elements other than Map.Entry and an Array

So you can use it as follows

Map map = ArrayUtils.toMap(arrayName);

And you have to import ArrayUtils first from:

import org.apache.commons.lang3.ArrayUtils;

Note: This is not a built-in method; you need the Apache Commons dependency!

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
Adam Ma
  • 624
  • 5
  • 16
0

Streams only look at one item at a time and they are independent of each other. This is to allow parallel streams where the order may or may not be preserved.

Java Streams are not suited for the kind of task you want to do here. Massage your data into single atomic objects first. In this case an ordinary for loop either over the indexes or using an iterator.

Thorbjørn Ravn Andersen
  • 73,784
  • 33
  • 194
  • 347
  • I think it's possible See Eran answer – Vinay Prajapati Jun 24 '18 at 13:21
  • @VinayPrajapati Read carefully. It uses a stream of the _indexes_ in the list and then access the list each and every time. _Technically_ that is using a stream, but in reality this is not how collections are intended to be processed. If I saw this code from you as a declared beginner in a peer review I would reject it. – Thorbjørn Ravn Andersen Jun 24 '18 at 13:25
  • But why? Is that a bad code or is something shouldn't be done while using streams? – Vinay Prajapati Jun 24 '18 at 13:28
  • 1
    @ThorbjørnRavnAndersen As the primary designer of `java.util.stream`, I would strongly disagree with your claim that this is not how they are intended to be used. Using a stream of indexes was explicitly one of the techniques we had in mind, because we knew that not all problems could be strictly described by stream-of-value. – Brian Goetz Jun 25 '18 at 15:42