Search code examples
javajava-stream

Java stream based on condition create list


Below code returns [Test11, Test33, Test44]. But I want is [Test11, Test2, Test33, Test44]. i.e When realName exists use it, else use the altName.

The line which i commented out is giving correct result. But getRealName method is being called twice. Is there any way to use the stream() to get the desired output that i want without calling the method twice? Please help.

public class Main {
    private static HashMap<String, String> myMap = new HashMap<>();
    public static void main(String[] args) {
        myMap.put("Test11", "Test1");
        myMap.put("Test33", "Test3");
        myMap.put("Test44", "Test4");

        List<String> list = new ArrayList<String>();
        list.add("Test1");
        list.add("Test2");
        list.add("Test3");
        list.add("Test4");


        List<String> result = list.stream().map(altName -> getRealName(altName)).
                filter(realName ->  Objects.nonNull(realName)).collect(Collectors.toList());

       /* List<String> result = list.stream()
                .map(altName -> getRealName(altName)!=null?getRealName(altName):altName)
                .collect(Collectors.toList());*/

        System.out.println(result);

    }

    private static String getRealName(String item) {
        for (Map.Entry<String, String> entry : myMap.entrySet()) {
            if (entry.getValue().equals(item)) {
                return entry.getKey();
            }
        }
        return null;
    }
}


Solution

  • Just put the result of getRealName in a variable before doing the logic:

    List<String> result = list.stream()
        .map(altName -> {
            var realName = getRealName(altName);
            return realName != null ? realName : altName;
        })
        .collect(Collectors.toList());
    

    If getRealName instead returned an Optional<String>, then you could use the .orElse method on it:

    List<String> result = list.stream()
        .map(altName -> getRealName(altName).orElse(altName)))
        .collect(Collectors.toList());
    

    By the way, it looks like you should turn your Map around (swap keys and values), because you are only querying it by the value. Maps are much more efficient and ergonomic if you query them by the key. Your getRealName-method would just be map.get(altname).