0

So I found a solution to my problem online and it works but I cannot visualise the exact step by step solution here. Also Id like to know how to do the same thing using more basic structures of a language like standard foreach loop.

UPDATE: so I got somehow to the parametrerised methods of sorted() and filtred() and I made it with filtering but no idea how to define the comparator for the rest of the methods in class that are supposed to use the universal sorted() method. Here's my code: package zad1;

 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.*;
 import java.util.function.Predicate;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;

public class ProgLang {

public LinkedHashMap<String, List<String>> ProgsMap = new LinkedHashMap<>();
public LinkedHashMap<String, List<String>> LangMap = new LinkedHashMap<>();
List<String> langs;
List<String> programmers;


public ProgLang(String file) {

    Pattern pattern = Pattern.compile("([A-Za-z0-9#+]+[\t[A-Za-z'-]+]+)");

    try {

        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
        String lang = bufferedReader.readLine();

        while (lang != null) {

            if (pattern.matcher(lang).find()) {


                String[] elements = lang.split("\t");
                langs = new ArrayList<String>();

                if (!langs.contains(elements[0])) {
                    langs.add(elements[0]);
                }
                programmers = new ArrayList<String>();

                for (int k = 1; k < elements.length; k++) {
                    programmers.add(elements[k]);
                }
                LangMap.put(elements[0], programmers);

                List<String> tmp_prog = new ArrayList<>();

                for (String programmer : programmers) {
                    for (String language : langs) {

                        if (ProgsMap.get(programmer) == null) {

                            ProgsMap.put(programmer, new ArrayList<>());
                            ProgsMap.get(programmer).add(language);
                        } else if (ProgsMap.get(programmer) != null) {

                            if (!ProgsMap.get(programmer).contains(language)) {
                                ProgsMap.get(programmer).add(language);
                            }
                        }
                    }
                }

                lang = bufferedReader.readLine();


            } else
                lang = bufferedReader.readLine();
        }


        System.out.println(ProgsMap);
        System.out.println("---------");
        System.out.println(LangMap);
        bufferedReader.close();

    } catch (IOException e) {
        e.getMessage();
        System.out.println(e.getMessage());
    }

}

public LinkedHashMap<String, List<String>> getLangsMap() {
    return LangMap;
}


public LinkedHashMap<String, List<String>> getProgsMap() {
    return ProgsMap;
}


public static <K, V> LinkedHashMap<K, List<V>> sorted(Map<K, List<V>> mapToSort, Comparator<Map.Entry<K, List<V>>> entryComparator) {

    LinkedHashMap<K, List<V>> sorted = new LinkedHashMap<>();
    mapToSort.entrySet().stream().sorted(entryComparator).forEach(kListEntry -> sorted.put(kListEntry.getKey(), kListEntry.getValue()));
    //przekazuje mape jako strumien informacji gdzie kazde z wejsc do mapy 
  tj. kazda para jest obslugiwana po kolei dzieki metodzie forEach za pomoca 
  podanego w parametrach comparatora
    return sorted;
   }
  // zrodlo pomocniecze: Java Coding Problems: Improve your Java Programming 
    skills by solving real-world Coding Challanges
    //Autor Anghel Leonard

  public static <K, V> LinkedHashMap<K, List<V>> filtered(Map<K, List<V>> 
   mapToFilter, Predicate<Map.Entry<K, List<V>>> entryPredicate) {

    LinkedHashMap<K, List<V>> filteredMap = new LinkedHashMap<>();
    mapToFilter.entrySet().stream().filter(entryPredicate).forEach(entry - 
  > filteredMap.put(entry.getKey(), entry.getValue()));
    return filteredMap;

   }

  public LinkedHashMap<String, List<String>> 
  getLangsMapSortedByNumOfProgs() 
 {
      sorted(LangMap, );
  }

  public LinkedHashMap<String, List<String>> 
  getProgsMapSortedByNumOfLangs() 
 {
      sorted(ProgsMap, //what next??????? how to definea comparator to 
  sort 
     given LinkedHashMap by the size of list in every entry?);
   }

     public LinkedHashMap<String,List<String>> 
     getProgsMapForNumOfLangsGreaterThan(int value){
       return filtered(ProgsMap, entry -> entry.getValue().size() > 
  value);
      }

  }
Zelefrion
  • 11
  • 3
  • 2
    what _specific_ part is not clear to you? – Eugene Nov 24 '19 at 19:36
  • It iterates over stream of map entries (key:value pairs) sorts those entries according to Comparator passed as method argument, after it is sorted it places data from those entries to LinkedHashMap (since it preserve insertion order), then that map is returned. – Pshemo Nov 24 '19 at 19:41

2 Answers2

1

You have the generic method that accepts two parameters, first one is generic Map with key anytype and value list of anytype

Map<any,List<any>>
Map<String, List<Integer>> map = Map.of();

And second one is generic Comparator corresponding to Map type to sort the map

Comparator<Map.Entry<String, List<Integer>>> com = Comparator.comparing(Map.Entry::getKey);

And in the method you are sorting the input Map and adding it to LinkedHashMap to save the sorted order

mapToSort.entrySet().stream().sorted(entryComparator).forEach(kListEntry -> sorted.put(kListEntry.getKey(), kListEntry.getValue()));

So you can do the complete operation in one stream by using Collectors.toMap and here is my fav site with perfect examples

public static <K, V> Map<K, List<V>> sorted(Map<K, List<V>> mapToSort,
        Comparator<Map.Entry<K, List<V>>> entryComparator) {

    LinkedHashMap<K, List<V>> sorted = mapToSort.entrySet().stream().sorted(entryComparator)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));

    return sorted;
}

You can also pass the different map objects of different types

Map<Integer, List<String>> map = Map.of();
Map<Double, List<Integer>> map = Map.of();

But if you try to pass different contract Map and Comparator like this, you will get compile time error

Map<String, Integer> map = Map.of();
Comparator<Map.Entry<String, Integer>> com = Comparator.comparing(Map.Entry::getKey);

Error :

 The method sorted(Map<K,List<V>>, Comparator<Map.Entry<K,List<V>>>) in the type 
 Class is not applicable for the arguments (Map<String,Integer>, Comparator<Map.Entry<String,Integer>>)
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
0

A map consists of key-value pairs, for example:

// key: value
   name: John
   surname: Smith

That, each of those key-value pairs is called an entry.

Here we're taking that map, converting the entries to a stream, and processing these entries.

In this case, we have following:

Convert the map into entries:

(name, John), (surname, Smith)

Sort the entries based on the comparator provided (e.g. Descending alphabetical key value)

(surname, Smith), (name, John) 

And then for each of them, add them to the sorted map, getting the key and the value.

In this case, we're inputing the keys in a certain order into a LinkedHashMap. Why would you want to do this depends on the problem you're trying to solve, which probably has to do with Java's implementation of the LinkedHashMap and entry ordering to improve performance.

It seems like a really niche problem, maybe you can fill us in on that to give you more info.

btuso
  • 85
  • 9