1

I have a following map:

Map<String, String> date = new HashMap();
date.put("2021-03-24",  "2021-03-26");
date.put("2021-03-03",  "2021-03-03");
date.put("2021-03-01",  "2021-03-03");
date.put("2021-03-25",  "2021-03-25");
date.put("2021-03-02",  "2021-03-03");
date.put("2021-03-01",  "2021-03-01");
date.put("2021-03-04",  "2021-03-04");

My requirement is to filter out the key value pairs, which have duplicate values, so the remaining key value pairs in the output should be as below:

2021-03-24= 2021-03-26,
2021-03-25= 2021-03-25,
2021-03-01= 2021-03-01,
2021-03-04= 2021-03-04,

I have used below lambda:

 Set<String> uniqueSet = date.values().stream()
                    .collect(Collectors.toMap(Function.identity(), v -> true, (a,b) -> false))
                    .entrySet().stream()
                    .filter(Map.Entry::getValue)
                    .map((Map.Entry::getKey))
                    .collect(Collectors.toSet());

But I don't want the result as a Set. I want the result as a Map.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
Geek
  • 15
  • 7
  • On what basis do you keep the entries/keys you've kept? And what's your current attempt to solve it? – ernest_k Mar 24 '21 at 06:47
  • Anything, you have tried so far? – Ravindra Ranwala Mar 24 '21 at 06:52
  • 1
    I edited my answer with my attempt – Geek Mar 24 '21 at 06:54
  • Do like this `Map result = date.entrySet().stream() .filter(entry -> date.values().stream().filter(v->v.equals(entry.getValue())).count()==1) .collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));` – Hadi J Mar 24 '21 at 07:03
  • @HadiJ, it does not return my desired output , result is this after using this :{2021-03-04=true, 2021-03-26=true, 2021-03-25=true, 2021-03-01=true} – Geek Mar 24 '21 at 07:09
  • @geek - in case of `2021-03-03` which one should be chosen and why? – Arvind Kumar Avinash Mar 24 '21 at 07:35
  • Basil Bourque - It was a wrong dupe target. Inverting the map is one of the strategies that I chose to solve it but there can many different ways to solve it. Also, my solution inverts the map twice. – Arvind Kumar Avinash Mar 24 '21 at 10:10

5 Answers5

4

You can invert the map (swap key with value) removing the duplicate values. In the code given below, (v1, v2) -> v2 means we want to keep the second value in case of a conflict. If you want to keep the first value, change it to (v1, v2) -> v1.

Demo:

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
        Map<String, String> date = new HashMap<>();
        date.put("2021-03-24", "2021-03-26");
        date.put("2021-03-03", "2021-03-03");
        date.put("2021-03-01", "2021-03-03");
        date.put("2021-03-25", "2021-03-25");
        date.put("2021-03-02", "2021-03-03");
        date.put("2021-03-01", "2021-03-01");
        date.put("2021-03-04", "2021-03-04");

        // Invert the map
        Map<String, String> invertedMap = date.entrySet().stream()
                .collect(Collectors.toMap(Entry::getValue, Entry::getKey, (v1, v2) -> v2));

        // Invert the inverted map
        Map<String, String> result = invertedMap.entrySet().stream()
                .collect(Collectors.toMap(Entry::getValue, Entry::getKey, (v1, v2) -> v2));

        result.entrySet().forEach(System.out::println);
    }
}

Output:

2021-03-04=2021-03-04
2021-03-25=2021-03-25
2021-03-02=2021-03-03
2021-03-24=2021-03-26
2021-03-01=2021-03-01
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
1

Here I write a code that prints your dates as per your requirement:

Set<String> existing = new HashSet<>();
date = date.entrySet()
        .stream()
        .filter(entry -> existing.add(entry.getValue()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

date.entrySet()
        .forEach(entry -> {
            System.out.println(entry.getKey() + " " + entry.getValue());
        });
ernest_k
  • 44,416
  • 5
  • 53
  • 99
1

Try this.

Map<String, String> result = date.entrySet().stream()
    .collect(Collectors.groupingBy(e -> e.getValue()))
    .values().stream()
    .filter(list -> list.size() == 1)
    .map(list -> list.get(0))
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
for (Entry<String, String> e : result.entrySet())
    System.out.println(e);

output:

2021-03-04=2021-03-04
2021-03-25=2021-03-25
2021-03-24=2021-03-26
2021-03-01=2021-03-01
0

Hi Please have a look.

public class FilterMap
{
    public static void main(String[] args) {
        Map<String, String> date = new HashMap();
        date.put("2021-03-24",  "2021-03-26");
        date.put("2021-03-03",  "2021-03-03");
        date.put("2021-03-01",  "2021-03-03");
        date.put("2021-03-25",  "2021-03-25");
        date.put("2021-03-02",  "2021-03-03");
        date.put("2021-03-01",  "2021-03-01");
        date.put("2021-03-04",  "2021-03-04");
        System.out.printf("Before: %s%n", date);

     // Set in which we keep the existing values
        Set<String> existing = new HashSet<>();// Set keeps unique values so it will help during filter
        date = date.entrySet()
                .stream()
                .filter(entry -> existing.add(entry.getValue()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        System.out.printf("After: %s%n", date);
    }
Raushan Kumar
  • 1,195
  • 12
  • 21
0
 Map<String, String> result = date.entrySet().stream()
                .filter(entry -> (Collections.frequency(date.values(), entry.getValue()) == 1))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));


for (Map.Entry<String, String> m : result.entrySet()) {
            System.out.println("Key : " + m.getKey() + "--------------" + " Value: " + m.getValue());
        }

Console output:

Key : 2021-03-04--------------  Value: 2021-03-04
Key : 2021-03-25--------------  Value: 2021-03-25
Key : 2021-03-24--------------  Value: 2021-03-26
Key : 2021-03-01--------------  Value: 2021-03-01

Note: Entry with ("2021-03-01", "2021-03-03") will not be there as it is overridden with ("2021-03-01", "2021-03-01")