Home > Blockchain >  Turn ordered List A & List B to Ordered List C
Turn ordered List A & List B to Ordered List C

Time:03-12

Here the problem I am having :

I have :

  • a List<String> names; provided by my GUI where the order is significative;
  • a List<CustomObject> customObjects; where customObject could have the same "name" attribut.

I need to return a List<CustomObject> customObjects; composed of one element for a name (any of them) with the same order than names.

I tried some things but I feel it has to nest a for with a stream and I think I'll have to do otherwise.

For exemple :

    Map<String, CustomObjects> map = customObjects.stream().filter(co -> names.contains(co.getName())).collect(Collectors.toMap(CustomObjects::getName, co->co));

for(String name : names) {
  customObjetsToReturn.add(map.get(name));
}

Or

    for (String name : names) {
  customObjects.stream().filter(co -> name.equals(co.getName())).findFirst().ifPresent(customObjectsToReturn::add);
}

CodePudding user response:

So basically you want to filter all CustomObject whose name appear in the names list and then you want to have distinct CustomObjects by the attribute name. If so something like below should do the trick:

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

....


List<String> names; //your names
List<CustomObject> customObjects; //your objs

List<CustomObject> filterd =
            customObjects.stream()
                         .filter(co -> names.contains(co.getName()))
                         .filter(distinctByKey(CustomObject::getName))
                         .collect(Collectors.toList());

public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

CodePudding user response:

You can obtain the resulting list by applying Collectors.toList() in the stream without creating a loop.


Update

I need to return a customObjectList where it size is the same of the inital nameList

customObjects have several items who have the same name

If I understood your intention correctly, the resulting list needs to be based on the values from the list of names.

The code below will be useful only if there's a particular rule on how to choose the object from the group of duplicates, it needs to be added as the third argument of the Collectors.toMap() (now it chooses the first encountered).

Map<String, CustomObjet> objByName =
            customObjects.stream()
                    .collect(Collectors.toMap(CustomObject::getName, 
                                                Function.identity()),
                                                (v1, v2) -> v1); // rule on how to dial with duplicates (when name is the same)

    List<CustomObjet> customObjetsToReturn =
            names.stream()
                    .filter(objByName::containsKey)
                    .map(objByName::get)
                    .collect(Collectors.toList());
  • Related