Java Ordered Map
The SortedMap interface (with the implementation TreeMap) should be your friend.
The interface has the methods:
keySet()
which returns a set of the keys in ascending ordervalues()
which returns a collection of all values in the ascending order of the corresponding keys
So this interface fulfills exactly your requirements. However, the keys must have a meaningful order. Otherwise you can used the LinkedHashMap where the order is determined by the insertion order.
Java Class that implements Map and keeps insertion order?
I suggest a LinkedHashMap
or a TreeMap
. A LinkedHashMap
keeps the keys in the order they were inserted, while a TreeMap
is kept sorted via a Comparator
or the natural Comparable
ordering of the keys.
Since it doesn't have to keep the elements sorted, LinkedHashMap
should be faster for most cases; TreeMap
has O(log n)
performance for containsKey
, get
, put
, and remove
, according to the Javadocs, while LinkedHashMap
is O(1)
for each.
If your API that only expects a predictable sort order, as opposed to a specific sort order, consider using the interfaces these two classes implement, NavigableMap
or SortedMap
. This will allow you not to leak specific implementations into your API and switch to either of those specific classes or a completely different implementation at will afterwards.
How to preserve insertion order in HashMap?
LinkedHashMap
is precisely what you're looking for.
It is exactly like HashMap
, except that when you iterate over it, it presents the items in the insertion order.
Ordered List Map implementation in Java
If you need your items in a specific order, LinkedHashMap is your friend - it keeps items in insertion order. TreeMap will keep your items in an order defined by either a Comparator you give or a compareTo method of the key.
Converting Java map into ordered collection based on map values
Use a LinkedHashMap instead of a Map. The difference is that the first one has an order, so when you sort it it will remain sorted (until you modify or add new elements)
By the way, you can stream over a Map
answerCounts.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.forEach(System.out::println);
This will sort the Map but in the wrong order, and i can't find a way to reverse it
Ordering MapString, Integer by ListString using streams
The HashMap
cannot be used to store orderedData
because it does not guarantee ordering of its keys, so LinkedHashMap
should be used which maintains insertion order.
Ordering by the data presented in orderSequence
using streams may be implemented in two modes:
- Keep only the values available in
nonOrderedData
:
Map<String, Integer> nonOrderedData = Map.of(
"b", 1, "e", 4, "a", 0, "o", 5, "d", 7
);
List<String> orderSequence = Arrays.asList(
"a", "e", "i", "o", "u", "b", "c", "d"
);
Map<String, Integer> reordered = orderSequence
.stream()
.filter(nonOrderedData::containsKey)
.collect(Collectors.toMap(
key -> key, nonOrderedData::get,
(v1, v2) -> v1, LinkedHashMap::new
));
System.out.println(reordered);
Output:
{a=0, e=4, o=5, b=1, d=7}
It is similar to INNER JOIN
between orderSequence
and nonOrderedData
.
- Filling
reorderedData
with some default value if the key fromorderSequence
is missing innonOrderedData
:
Map<String, Integer> reorderedWithDefault = orderSequence
.stream()
.collect(Collectors.toMap(
key -> key, nonOrderedData.getOrDefault(key, -1),
(v1, v2) -> v1, LinkedHashMap::new
));
System.out.println(reorderedWithDefault);
Output:
{a=0, e=4, i=-1, o=5, u=-1, b=1, c=-1, d=7}
It is similar to LEFT JOIN
between orderSequence
and nonOrderedData
.
Update
In the above-mentioned implementations the key-value pairs in nonOrderedData
that do not match to the keys in orderSequence
are skipped altogether. Such keys may be tracked (and added later to the reordered
result) using Map::remove (Object key)
which returns a value of the key being removed.
However, the following two code examples modify the state of nonOrderedData
outside the stream execution.
- Keep the keys and related values only from
nonOrderedData
, place the non-matched pairs to the end:
Map<String, Integer> nonOrderedData = new HashMap<>(Map.of(
"b", 1, "e", 4, "z", 8, "a", 0, "q", 6,
"f", 5, "d", 7
));
List<String> orderSequence = Arrays.asList("a", "e", "i", "o", "u", "b", "c", "d");
Map<String, Integer> reordered = orderSequence
.stream()
.filter(nonOrderedData::containsKey)
.collect(Collectors.toMap(
key -> key, nonOrderedData::remove,
(v1, v2) -> v1, LinkedHashMap::new
));
SortedMap<String, Integer> remainder = new TreeMap<>(nonOrderedData);
System.out.println("remained: " + remainder);
reordered.putAll(remainder);
System.out.println(reordered);
Output:
remained: {f=5, q=6, z=8}
{a=0, e=4, b=1, d=7, f=5, q=6, z=8}
It is similar to RIGHT JOIN
between orderSequence
and nonOrderedData
.
- Keep all values from both
orderSequence
andnonOrderedData
similar toFULL JOIN
Here default values will be provided for the non-mapped keys in orderSequence
and non-matched keys from nonOrderedData
will be added to the end.
Map<String, Integer> reorderedFull = orderSequence
.stream()
.peek(key -> nonOrderedData.computeIfAbsent(key, (k) -> -1)) // default value
.collect(Collectors.toMap(
key -> key, nonOrderedData::remove,
(v1, v2) -> v1, LinkedHashMap::new
));
SortedMap<String, Integer> remainderFull = new TreeMap<>(nonOrderedData);
System.out.println("remained: " + remainderFull);
reorderedFull.putAll(remainderFull);
System.out.println(reorderedFull);
Output:
remained: {f=5, q=6, z=8}
{a=0, e=4, i=-1, o=-1, u=-1, b=1, c=-1, d=7, f=5, q=6, z=8}
Related Topics
How to Read All of Inputstream in Server Socket Java
Why Can't Primitive Data Types Be "Null" in Java
What Is the Point of Setters and Getters in Java
Does Java Have Built in Libraries for Audio _Synthesis_
Efficient Swapping of Elements of an Array in Java
What Is Difference Between Crudrepository and JPArepository Interfaces in Spring Data JPA
What Are the Differences Between Arraylist and Vector
What Is the Significance of Load Factor in Hashmap
Installed Java 7 on MAC Os X But Terminal Is Still Using Version 6
How Is Countdownlatch Used in Java Multithreading
Running Rmi Server, Classnotfound
Custom JSON Deserializer Using Gson
Java Regular Expression to Extract Content Within Square Brackets
Adding Image to Jbutton with Foreground Label
No-Throw Virtualmachineerror Guarantees
Missing Return Statement for If/Else Statement