1

What i've tried is creating an iterator for the list and using stream on the set as such

Set //some object which has a getId method
Iterator<String> iterator = list.iterator();
someSet.stream()
     .map(Collectors.toMap(e -> e.getId(), e -> iterator.next() );

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
Akbar Hashmi
  • 57
  • 1
  • 7
  • 1
    this will break in parallel execution, most probably. – Eugene Apr 12 '20 at 17:27
  • Could you tell please what are you trying to achieve? – Echoinacup Apr 12 '20 at 17:30
  • don't depend on the order of items in a set or a list or any structure. That in itself is very bad – Nithin Apr 12 '20 at 17:33
  • my point is - this is _fine_ when you run sequentially (as long as you do not care about order), but will break as soon as you add `parallel`, this is because the `itearator` from a `Set` is not thread-safe. since a stream is supposed to work both in parallel and sequential - I would not do this if I were you. – Eugene Apr 12 '20 at 17:33
  • Im trying to iterate through a list and a set in parallel (both are of the same size). For each object in the set, Id like to call its function getId and map whatever that returns to the element(of same index) in the list. – Akbar Hashmi Apr 12 '20 at 17:35
  • you should refactor where you are creating this list, probably there should be some relation b/w list content and set and then use that to match , don't depend on order of items – Nithin Apr 12 '20 at 17:38
  • You can convert the `Set` to a `List` for the purpose of iteration if you desire sequential access of elements from the collection. @AkbarHashmi – Naman Apr 12 '20 at 17:38
  • We can assume the order to be random in both list/set and that the two don't depend on each other. Is there a better way to this then? – Akbar Hashmi Apr 12 '20 at 17:38

2 Answers2

1

I think, what you wat to achieve is called "zip" in fuctional programming. This would be in Java to make a new stream from two existing streams by combining each of two corresponding elements of the given streams.

Look at this question to see how to do it:

Zipping streams using JDK8 with lambda (java.util.stream.Streams.zip)

Donat
  • 4,157
  • 3
  • 11
  • 26
1

The Stream API is designed to work and iterate through one and only one collection and no more.

If you want to achieve such iteration called "zipping", as mentioned in the another answer, you have to iterate the indices. Since Set is not ordered, you have to use List instead and know the order is not predictable.

However, the usage of Stream API should be fine here:

Set<MyObject> set = ...                                             // MyObject with getId method
List<MyObject> listFromSet = new ArrayList<>(set);
List<MyObject> list = ...                                           // existing list

IntStream.range(0, Math.min(list.size(), listFromSet.size()))
        .mapToObj(index -> new AbstractMap.SimpleEntry<>(
            listFromSet.get(index).getId(),                         // key
            list.get(index))                                        // value
        )
        .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); // to Map

Few notes:

  • To know the highest number you can iterate through, you need ti find a lower from the sizes of the iterables: Math.min(list.size(), listFromSet.size()).
  • map(Collector.toMap(...)) doesn't convert a Stream to Map but is not a valid construct, moreover the method map is not a terminal operation. Use .collect(Collectors.toMap(...)) instead which is.
  • Not all the keys from set might be used, not all the values from list might be used, there is no guaranteed order of the keys and the matching key-value will be random.
  • If I were to implement this, I'd definetly go for the simple for-loop iteration over the Streams.
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183