简体   繁体   中英

How to return the key with the most associated values inside a HashMap

I currently have a HashMap in the form 'HashMap<String, HashSet>', which contains a key (an item) and a value (a HashSet of all items associated with that item).

I am trying to write a method within the class that retrieves the key (item) with the most values (items) associated with it and am not sure how to do this, for example:

Input:

myItems.mostValues();

Output:

Item1 is has the most interactions, as it is connected to 3 items: {X, Y, Z}
map.entrySet().stream()
                .filter(entry -> entry.getValue() != null)
                .max(Comparator.comparingInt(e -> e.getValue().size()))
                .map(entry -> map.get(entry.getKey()));
 map.values()
    .stream()
    .filter(Objects::nonNull)
    .mapToInt(val -> val.size())
    .max()
    .ifPresent(val-> map.keySet()
            .stream()
            .filter(key-> map.get(key) != null && map.get(key).size() == val)
            .forEach(System.out::println)
    );

Note: Sergei 's answer handles null and is O(n) using streams. Sergey 's answer outputs all the possible values

Streams with sort (less efficient) - O(nlogn)

  1. Stream the elements
  2. Reverse sort by size of Set
  3. Get the key of the element (or value directly and print it)
  4. If key is retrieved, then lookup the key in myItems and print value
myItems.entrySet().stream().filter(e -> e.getValue() != null)
  .sorted((a, b) -> b.getValue().size() - a.getValue().size())
  .findFirst().orElse(new SimpleImmutableEntry<>(null, null))
  .getValue());

Normal for loop - O(n)

  1. Iterate over all entires
  2. Keep track of max size at each iteration
  int maxItem = 0;
  Set<String> maxValues = null;
  for (Map.Entry<String, Set<String>> e : myItems.entrySet()) {
    if (e.getValue() == null) {
      return null;
    }
    if (maxItem < e.getValue().size()) {
      maxValues = e.getValue();
      maxItem = maxValues.size();
    }
 }

Updated: Since the answer was accepted, i will add the other O(n) solutions with null handling on top of Sergey and Sergei answers.

The following code assumes initial Map is non null.

Get maximum one- Stream O(n)

  1. Stream values
  2. Ignore null values
  3. Get the max sized value (optional)
  4. if empty, then return null
Map<String, Set<String>> myItems = new HashMap<>(); // input
myItems.put("a", new HashSet<>(Arrays.asList("a", "b", "c")));
myItems.put("b", new HashSet<>(Arrays.asList("b", "c")));

Set<String> result = myItems.values().stream()
  .filter(Objects::nonNull) // get only non-null
  .max(Comparator.comparing(Set::size)) // get the max size
  .orElse(null); // avoid optional.get() error incase of no results - can use new HashSet<>() also

Stream - Get all Maximum - O(n)

Find maximum size (or -1 if no elements)

  1. Stream values
  2. Ignore null values
  3. Transform to value to its size
  4. Find max size
  5. Stream values
  6. Ignore null values
  7. Select values with size as max size
  8. Collect all the values as List
Map<String, Set<String>> myItems = new HashMap<>(); // input
myItems.put("a", new HashSet<>(Arrays.asList("a", "b", "c")));
myItems.put("b", new HashSet<>(Arrays.asList("x", "y", "z")));
myItems.put("c", new HashSet<>(Arrays.asList("a")));

List<Set<String>> result = new ArrayList<>();
myItems.values().stream()
  .filter(Objects::nonNull) // get only non-null
  .mapToInt(Set::size)
  .max()
  .ifPresent(val -> myItems.values().stream()
    .filter(Objects::nonNull)
    .filter(v -> v.size() == val)
    .forEach(v -> result.add(v)));

Usage of Streams with lambda/method references

  1. Whenever possible try to use the method references using :: as this helps to understand the object type( Set::size ) when required and abstracts type for common operations( Objects::nonNull ).
  2. In real code, always handle null (even with Optional)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM