I have implemented the following method that provides an overview over String
s and their occurrences in the values of a Map<String, List<String>>
:
public static Map<String, Long> getValueItemOccurrences(Map<String, List<String>> map) {
Map<String, Long> occurrencesOfValueItems = new HashMap<>();
map.forEach((key, value) -> {
value.forEach(item -> {
if (occurrencesOfValueItems.containsKey(item)) {
occurrencesOfValueItems.put(item, occurrencesOfValueItems.get(item) + 1);
} else {
occurrencesOfValueItems.put(item, 1L);
}
});
});
return occurrencesOfValueItems;
}
I have tested it with a single JUnit test and the test succeeds. Here it is (now also including the imports):
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
class TryoutTest {
static Map<String, List<String>> items = new HashMap<>();
static List<String> largeList = new ArrayList<String>();
static List<String> mediumList = new ArrayList<String>();
static List<String> smallList = new ArrayList<String>();
static List<String> differentLargeList = new ArrayList<String>();
static List<String> differentSmallList = new ArrayList<String>();
static List<String> anotherList = new ArrayList<String>();
static List<String> someList = new ArrayList<String>();
static List<String> justAList = new ArrayList<String>();
@BeforeAll
static void setup() {
largeList.add("Alfred");
largeList.add("Bakari");
largeList.add("Christian");
largeList.add("Dong");
largeList.add("Etienne");
largeList.add("Francesco");
largeList.add("Guido");
largeList.add("Henrik");
largeList.add("Ivan");
largeList.add("Jos");
largeList.add("Kumar");
largeList.add("Leonard");
largeList.add("Marcin");
largeList.add("Nico");
largeList.add("Olof");
items.put("fifteen-01", largeList);
mediumList.add("Petar");
mediumList.add("Quentin");
mediumList.add("Renato");
mediumList.add("Sadio");
mediumList.add("Tomislav");
mediumList.add("Ulrich");
mediumList.add("Volkan");
mediumList.add("Wladimir");
items.put("eight-01", mediumList);
smallList.add("Xavier");
smallList.add("Yves");
smallList.add("Zinedine");
smallList.add("Alfred");
items.put("four-01", smallList);
differentLargeList.add("Bakari");
differentLargeList.add("Christian");
differentLargeList.add("Dong");
differentLargeList.add("Etienne");
differentLargeList.add("Francesco");
differentLargeList.add("Xavier");
differentLargeList.add("Yves");
differentLargeList.add("Wladimir");
differentLargeList.add("Jens");
differentLargeList.add("Hong");
differentLargeList.add("Le");
differentLargeList.add("Leigh");
differentLargeList.add("Manfred");
differentLargeList.add("Anders");
differentLargeList.add("Rafal");
items.put("fifteen-02", differentLargeList);
differentSmallList.add("Dario");
differentSmallList.add("Mohammad");
differentSmallList.add("Abdul");
differentSmallList.add("Alfred");
items.put("four-02", differentSmallList);
anotherList.add("Kenneth");
anotherList.add("Hong");
anotherList.add("Bakari");
anotherList.add("Ulrich");
anotherList.add("Henrik");
anotherList.add("Bernd");
anotherList.add("Samuel");
anotherList.add("Ibrahim");
items.put("eight-02", anotherList);
someList.add("Kumar");
someList.add("Konrad");
someList.add("Bakari");
someList.add("Francesco");
someList.add("Leigh");
someList.add("Yves");
items.put("six-01", someList);
justAList.add("Bakari");
items.put("one-01", justAList);
}
@Test
void valueOccurrencesTest() {
Map<String, Integer> expected = new HashMap<>();
expected.put("Abdul", 1);
expected.put("Alfred", 3);
expected.put("Anders", 1);
expected.put("Bakari", 5);
expected.put("Bernd", 1);
expected.put("Christian", 2);
expected.put("Dario", 1);
expected.put("Dong", 2);
expected.put("Etienne", 2);
expected.put("Francesco", 3);
expected.put("Guido", 1);
expected.put("Henrik", 2);
expected.put("Hong", 2);
expected.put("Ibrahim", 1);
expected.put("Ivan", 1);
expected.put("Jens", 1);
expected.put("Jos", 1);
expected.put("Kenneth", 1);
expected.put("Konrad", 1);
expected.put("Kumar", 2);
expected.put("Le", 1);
expected.put("Leigh", 2);
expected.put("Leonard", 1);
expected.put("Manfred", 1);
expected.put("Marcin", 1);
expected.put("Mohammad", 1);
expected.put("Nico", 1);
expected.put("Olof", 1);
expected.put("Petar", 1);
expected.put("Quentin", 1);
expected.put("Rafal", 1);
expected.put("Renato", 1);
expected.put("Sadio", 1);
expected.put("Samuel", 1);
expected.put("Tomislav", 1);
expected.put("Ulrich", 2);
expected.put("Volkan", 1);
expected.put("Wladimir", 2);
expected.put("Xavier", 2);
expected.put("Yves", 3);
expected.put("Zinedine", 1);
assertThat(FunctionalMain.getValueItemOccurrences(items), is(expected));
}
}
When I change the implementation of the method to
public static Map<String, Long> getValueItemOccurrences(Map<String, List<String>> map) {
return map.values().stream()
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}
the test case fails, stating that the resulting map is not equal to the expected one. See this eclipse screenshot, which shows that, obviously, the order of elements makes the test fail:
Is it really just that? I think I have read that HashMap
s generally don't guarantee any order of keys.
My (quite long) question is: What can I do to make the stream API call produce a result that passes the test or do I have to change the test case, maybe use a different assertion?
Some sub-questions are:
- is there an alternative/better way to use the stream API for this method?
- Do I have to return a specific
Map
implementation if order matters (TreeMap
, maybe)?