Resorting a TreeMap in Java - java

I searched the web(and Stackoverflow) a lot but couldn't exactly found what I was looking for. Also couldn't really understand the concept.
As a Java assignment I have a treeMap storing some values in it.
static Map<String, Double> customers = new TreeMap<String, Double>();
Naturally it stores them ascending by it's String values. But I want it to store it's values ascending by it's Double values. How can I achieve this by a comparator? Details would be much appreciated.
Also again in this assignment I've another, separate treeMap which stores different values. Again declared like below:
static Map<String, Double> customers = new TreeMap<String, Double>();
It's okay for it to store it's values ascending by String. I'm using it like this to print out it's values but I also need to print it's values in ascending order sorted by Double. So how can I re-sort a treeMap. Again, details would be much appreciated.

You cannot re-sort a TreeMap. It has a fixed iteration order, determined at TreeMap construct-time. If you want a different sort order, use a different data structure.
I'm using it like this to print out it's values but I also need to print it's values in ascending order sorted by Double.
So don't worry about sorting the TreeMap. Create a List<Double> of the values in the map, and sort those.
List<Double> values = new ArrayList<Double>(customers.values());
Collections.sort(values);
System.out.println(values);

Make another map:
Map<Double, String> values = new TreeMap<Double, String>();
and always add to both maps (e.g. via a helper method). Unless there are memory constraints, you will get your customers maps sorted by customer and values sorted by whatever the Double value represents.
If you can have duplicate values, you can make a list (or a set, depending on the requirements) of customers instead:
Map<Double, List<String>> values = new TreeMap<Double, List<String>>();

Related

Collectors.groupingBy() returns result sorted in ascending order java

I am sending result in descending order but I get output with ascending order
List<myEntity> myData = new ArrayList<>();
Map<Integer,List<myEntity>> myid = new LinkedHashMap<>();
try {
myData = myService.getData(id);
myid = myData.stream().collect(Collectors.groupingBy(myEntity::getDataId));
Here mydata is sorted by desc order but after creating collections by group data id my list get sorted with ascending order. I want my collection list to be descending order not ascending order.
As #Holger described in Java 8 is not maintaining the order while grouping
, Collectors.groupingBy() returns a HashMap, which does not guarantee order.
Here is what you can do:
myid = myData.stream()
.collect(Collectors.groupingBy(MyEntity::getDataId,LinkedHashMap::new, toList()));
Would return a LinkedHashMap<Integer, List<MyEntity>>. The order will also be maintained as the list used by collector is ArrayList.
Collectors.groupingBy returns a HashMap without any order as such (as to why you see "some order" is explained here). The correct way to do this is to specify the Map that preserve the order inside the Collectors.groupingBy:
myData.stream()
.collect(Collectors.groupingBy(
MyEntity::getDataId,
LinkedHashMap::new,
Collectors.toList()
))
collect(Collectors.groupingBy()) returns a new Map which overwrites the variable to your previous LinkedHashMap. Your initial assignment is therefore futile. The exact type returned is undefined by the specs but in my test run it returned a HashMap. (Never assume this will always be the case across different versions and brands of Java!)
But the main issue is that you're storing Integer as keys. If the values of those keys is smaller than the modulus of the table inside the HashMap, they will just appear ordered (because the hashCode of an Integer is just it;s value). When I tested with 1000 Integer values of 0..999, the hashtable (the array as part of the inner workings of HashMap) appeared to be of size 2048. (Again, undocumented so don't assume it!)
In summary, the reason you see the results in ascending order is because of an implementation artifact, not because there's a specific reason.
You need reverse order of map. So In java 8 , i solved with this.
myData = myService.getData(id);
myid = myData.stream().collect(Collectors.groupingBy(myEntity::getDataId));
Map<Integer, List<myEntity>> finalMap = new LinkedHashMap<>();
myid.entrySet().stream()
.sorted(Map.Entry.<Integer, List<myEntity>>comparingByKey()
.reversed())
.forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));
System.out.println("FINAL RESULT : " + finalMap);
Entryset gives us Integers of this map of myid. So sort and get from first map which is myid and put in finalMap

Sorting a list after another one in Java

I need some help regarding list sorting. So, I have two lists, one which contains entities of type Sarcina(int Id,String desc) (lets call it ls1), and one which contains integers (lets call it ls2). Both lists have the same size. I am trying to sort both of them at the same time in descending order, interchanging the elements from the same positions in the both lists.
So, if I have ls1(Sarcina1,Sarcina2,Sarcina3) and ls2(3,5,4), and I sort ls2 as (5,4,3), I want to have in ls1 sorted as (Sarcina2,Sarcina3,Sarcina1).
Thank you.
You can use Treemap, Which maintains the sorted keys. Here you want to sort your Integers, so add them as keys and add your strings as values of a Treemap. It'll automatically sort it. So try someting like following:
TreeMap tm = new TreeMap();
// Put elements to the map
//Here "your_integer" is key and "your_string" is value in our Treemap
tm.put("your_integer","your_string");
tm.put("your_integer","your_string");
now tm is what you want. which has strings sorted according to your integers.

How to preserve the values ordering of a sorted map?

I have a sorted map and would like to retrieve the values in the order of their corresponding keys. I.e. if my sorted map has (1,6), (2,4), (3,1), I want to retrieve [6,4,1].
Is there something faster than iterating over the sorted map like so?
SortedMap<Double, Double> sortedMap = new TreeMap<Double, Double>(sortedMap.size());
List<Double> values = new ArrayList<Double>();
for (Entry<Double, Double> entry : sortedMap.entrySet()) {
values.add(entry.getValue());
}
I don't think simply doing:
values = new ArrayList<Double>(sortedMap.values())
would work since sortedMap.values() returns a Collection with no guarantees on the order but iterating over the map doesn't strike me as efficient.
sortedMap.values() returns a Collection with no guarantees on the order
According to docs for SortedMap the order is guaranteed, see:
http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html#values()
Why do you think iterating over a sorted map is slow? In order to retrieve all the values you would have to eventually iterate through the entire Map. So the time complexity will always be O(n).

Sort keys of multimap by highest value they contain

I using a Guava MultiMap (impl LinkedListMultimap) to allow me to store multiple values for a key, but then I want to sort the map by the highest value and return the keys.
i.e
After first run I have
key1:{13}
key2:{7}
key3:{11}
After second run I now have
key1:{13,14}
key2:{7,18}
key3:{11,1}
After third run I now have
key1:{13,14,16}
key2:{7,18,6}
key3:{11,1,22}
I want an order of
key3
key2
key1
and I want to output the keys (I dont need to know the values any longer)
I cant work out a way to do that, I dont have to use MultiMap it just looked like it might help
If I were you, I'd start by not using a Multimap, but rather, using a Map to track the greatest value associated with each key. Then, you have a Map<String, Integer>, and if you don't need to save the Map afterwards, then I'd do something like
final Map<String, Integer> map = ...
return Ordering.natural().onResultOf(Functions.forMap(map)).reverse()
// a comparator to compare strings in descending order of their
// associated values
.immutableSortedCopy(map.keySet());
To unpack a bit:
Ordering.natural() // the natural ordering on integers
.onResultOf(
Functions.forMap(map) // use the Map<String, Integer> as a Function
// this ordering now compares Strings by the natural ordering of
// the integers they're mapped to
.reverse(); // reverses the ordering, so it now sorts in descending order
What I would do is stick the entrySet into a TreeSet with a custom comparator. Then pull out the keys.
sortedEntries = Sets.newTreeSet(comparator).addAll(multimap.entries());
return Collections2.transform(sortedEntries, keyExtractor);
The implementation of keyExtractor, comparator and parametrization is left as an exercise to the reader.

How can I iterate starting at a particular key in a LinkedHashMap?

If I have a data structure
Stock
{
String Symbol;
LinkedHashMap<Date,Double> DateForPrice;
}
I know in the LinkedHashMap, I can get the stock price of specific date without traversing the whole list.
However, if I want to iterate through the LinkedHashMap of DateForPrice starting from a specific date, are there any way to do it without traversing the whole list?
LinkedHashMap doesn’t offer a way to start iterating in the middle of its ordered view of the map’s data. Supposing your use case is really that you want all dates after some Date d and to iterate those, then you should probably store your map as a TreeMap. An important distinction here is that LinkedHashMap’s ordering is the insertion-order, and our supposed use-case here is that you want the natural key-order. TreeMaps maintain such a view, sorting the contents of the map by the map’s key.
TreeMaps have the additional benefit of allowing you to create slices of the map based on the key, so you can call tailMap(K k), to return the map with all keys occurring after k. In this case, you can call tailMap with your starting point, d.
e.g.:
TreeMap<Date, Double> dateForPrice;
// load up dateForPrice
Date start = // the point to start your iteration
for(Entry<Date, Double> entry : dateForPrice.tailMap(start).entrySet()){
// loop code
}
tailMap method returns SortedMap, which is not iterable. But it has entrySet method returning Set, which is subinterface of Iterable.
Conveniently, if you want to keep storing your data in a LinkedHashMap you can simply load up a TreeMap with your current instance (with some performance tradeoff, of course):
TreeMap<Date, Double> dateSortedDateForPrice = new TreeMap<Date, Double>(dateForPrice);
I'd suggest to use TreeMap instead - it will be sorted by date and you can use tailMap to get the required portion

Categories