vijayashankard
vijayashankard

Reputation: 751

Refactoring Java 8 stream code

I have implemented the following code using Java 8.

Map<String, String> coMap = getHashMap();

String newCoName = coMap.entrySet()
                     .stream()
                     .filter(coEntry -> coEntry.getValue().equals(newcoId))
                     .map(coEntry -> coEntry.getKey())
                     .collect(Collectors.joining());


String oldCoName = coMap.entrySet()
                     .stream()
                     .filter(coEntry -> coEntry.getValue().equals(oldcoId))
                     .map(coEntry -> coEntry.getKey())
                     .collect(Collectors.joining());

Now. I want to know any better way of doing this instead of repeating the same lines of code twice.

Upvotes: 2

Views: 2489

Answers (5)

Harmlezz
Harmlezz

Reputation: 8068

You may use this helper method:

public static String join(Map<String, String> map, String value) {
    return map.keySet().stream()
            .filter(key -> Objects.equals(map.get(key), value))
            .collect(Collectors.joining());
}

Here some example code using the method:

    Map<String, String> coMap = new HashMap<>();
    coMap.put("A", null);
    coMap.put("B", "V");
    coMap.put("C", "V");
    coMap.put("D", "Z");
    coMap.put("E", "Z");
    coMap.put("F", null);

    System.out.println("Vs: " + join(coMap, "V"));
    System.out.println("Zs: " + join(coMap, "Z"));

And here the output:

Vs: BC
Zs: DE

Upvotes: 0

Eran
Eran

Reputation: 393831

A bigger issue than repeating the same code twice is executing the same code twice.

It would be more efficient to run a single Stream pipeline to produce your output :

Map<String,String> keysByValue =
            coMap.entrySet()
                 .stream()
                 .collect(Collectors.groupingBy(Map.Entry::getValue,
                                                Collectors.mapping(Map.Entry::getKey,
                                                                   Collectors.joining())));

This would give you for each value of your original Map (not only the two values your original code is searching for), the joint keys having that value.

Then you can extract from the Map the data you need :

String newCoName = keysByValue.get(newcoId);
String oldCoName = keysByValue.get(oldcoId);

Sample input and output :

Map<String,String> coMap = new HashMap<> ();
coMap.put("a","foo");
coMap.put("b","foo");
coMap.put("c","bar");
coMap.put("d","bar");
Map<String,String> keysByValue = ... // same as the code above
String newValueKeys = keysByValue.get("foo");
String oldValueKeys = keysByValue.get("bar");
System.out.println (newValueKeys);
System.out.println (oldValueKeys);

Output :

ab
cd

Upvotes: 10

Viet
Viet

Reputation: 3409

Other way uses with FunctionalInterface Predicate, your condition filter will be dynamic

public static Predicate<Map.Entry> getPredicate(String col) {
    return p -> p.getValue().equals(col);
}

public static String getName(HashMap<String, String> coMap, Predicate<Map.Entry> predicate) {
    return coMap.entrySet()
            .stream()
            .filter(predicate)
            .map(coEntry -> coEntry.getKey())
            .collect(Collectors.joining());
}

Calling in your code:

  getName(coMap, getPredicate(newcoId));
  getName(coMap, getPredicate(oldcoId));

Upvotes: 1

Peter Gelderbloem
Peter Gelderbloem

Reputation: 512

most IDE's can refactor it for you using "Extract Method" refactoring: http://refactoring.com/catalog/extractMethod.html or you can do it by hand

Upvotes: 0

baao
baao

Reputation: 73241

Since the whole difference is an id, a simple method does that for you.

String getName(int id) { // supposed id is an integer
    return coMap.entrySet()
             .stream()
             .filter(coEntry -> coEntry.getValue().equals(id))
             .map(coEntry -> coEntry.getKey())
             .collect(Collectors.joining()); 
}

Upvotes: 5

Related Questions