Sorting and Filtering Maps Using Generics I had a test for a Java-position where they asked me to manipulate JSON-data from an API. 

Once my overall parsing of the data into Maps were done.

The test required me among other things to implement:


Parameter for sorting the data (ASC, DESC) in Maps.
Parameter for filtering the selection of names in Maps.
Parameter for only showing data with odd or even occurrences in Maps.


I passed the test, but did not get the job with the feedback: "How you implemented the sorting and filtering of the maps seemed sloppy, and it seems like you rushed through that part of the test and there's no real code-maintainability in mind for these."

So my question is: How could I have done this implementation in a better way? What flaws do you see?

These maps contains the parsed JSON-data, you will see these being used below.

public static Map&lt;String, Integer&gt; firstNames; /** K= names, V= occurrences of that name **/
public static Map&lt;String, Integer&gt; surNames;


SortMap.java

public class SortMap {

    /**
     * ascending = 1, descending != 1.
     */
    public static &lt;K, V extends Comparable&lt;V&gt;&gt; Map&lt;K, V&gt; sortByValues (final Map&lt;K, V&gt; unsortedMap, int ascending) {
        Map&lt;K,V&gt; sortedMap = new LinkedHashMap&lt;&gt;();
        unsortedMap.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue((Comparator&lt;? super V&gt;) (ascending == 1 ? Comparator.naturalOrder() : Comparator.reverseOrder())))
                .forEachOrdered(x -&gt; sortedMap.put(x.getKey(), x.getValue()));
        return sortedMap;
    }

    public static &lt;K extends Comparable&lt;? super K&gt;, V&gt; Map&lt;K, V&gt; sortByKey(Map&lt;K, V&gt; unsortedMap, int ascending) {
        Map&lt;K,V&gt; sortedMap = new LinkedHashMap&lt;&gt;();
        unsortedMap.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey((Comparator&lt;? super K&gt;) (ascending == 1 ? Comparator.naturalOrder() : Comparator.reverseOrder())))
                .forEachOrdered(x -&gt; sortedMap.put(x.getKey(), x.getValue()));
        return sortedMap;
    }
}


Usages I provided to solve the tasks:

Map&lt;String, Integer&gt; firstNamesSorted = SortMap.sortByKey(firstNames,-1);
Map&lt;String, Integer&gt; surNamesSorted = SortMap.sortByKey(surNames,1);




FilterMap.java

public class FilterMap {

    public static &lt;K, V&gt; Map&lt;K, V&gt; filterByKey(Map&lt;K, V&gt; map, Predicate&lt;K&gt; predicate) {
        return map.entrySet()
                .stream()
                .filter(entry -&gt; predicate.test(entry.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    public static &lt;K, V&gt; Map&lt;K, V&gt; filterByValue(Map&lt;K, V&gt; map, Predicate&lt;V&gt; predicate) {
        return map.entrySet()
                .stream()
                .filter(entry -&gt; predicate.test(entry.getValue()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

}


Usages I provided to solve the tasks:

Map&lt;String, Integer&gt; filterUnevenNumbers = FilterMap.filterByValue(firstNames, value -&gt; value % 2 == 0);
Map&lt;String, Integer&gt; filterNames = FilterMap.filterByKey(firstNames, value -&gt; value.matches("(?i).*as.*"));


My own reflections of my code is:

Sorting:


-Could have used an enum instead of an int, but using any modern codeeditor you will see my javaDocs comment and also the ascending variable that you provide input for (removed javaDocs comments to reduce clutter in this instance).
+Uses generics.


Filtering:


+Uses generics.
+Dynamic implementation that can filter basically anything as long as you can create the expression using lambdas.
+Can be used for alot more purposes than what they asked for.
Assuming the requirement was to maintain initial map as immutable object -- just a few concerns re those new statements in sorting. They violate SRP, at least. Either accept already created (mutable) to populate with results, or (I prefer) accept a factory to get one. Same apples to collection step in filtering.

If, however, it is given that input map can be mutated during the process, then whole solution should be written with this in mind and, perhaps, stream is not the right choice here.