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
Related
I've got a Multimap that was originally created with the following statement:
ListMultimap<String, MyCustomObject> ids = MultimapBuilder.treeKeys().arrayListValues().build();
I'd like to be able to provide an offset and a limit so that I can turn my multimap into a smaller multimap that holds only keys between the 5th and 10th element of the original multimap (along with their corresponding values). The original Multimap may have a huge number of keys, so I don't want to iterate through the keys and call ids.get(key) if I can avoid it because it might be slow. Is there a good way of doing this? It's ok if your solution contains ids.get(key), I just prefer solutions that don't do that if that's even possible.
If you are talking about the ListMultiMap from guava, unfortunately you don't have many options, but I can think in somes that could help. Since the ListMultiMap doesn't implements List or Map you will need get the entries and transform into a list, list/arrays have O(1) time operation in addition so, calling a List list = new ArrayList(ids.entries()) will cost nothing, from here you can get a subset of the list like you said with List smallList = list.subList(5, 11) other O(1) operation, since List uses arrays, it will don't need iterate to reach these elements to create a new list, just pick elements between the positions.
Let's say I have a HashMap of Latitude/Longitudes + Names associated, and a separate ArrayList of the same Latitude/Longitudes that have been sorted by the nearest to my current location. How to I sort the HashMap to be in the same order as the ArrayList. If this is too complex then is there away to sort the initial HashMap by the nearest Latitude/Longitudes?
I think it is better to use LinkedHashMap (a Map that has order).
You can create a new LinkedHashMap and insert Latitude/Longitudes to it based on the ArrayList that you have (sorted list).
Remember LinkedHashMap is ordered based on the insertion.
I have the following key-value system (HashMap) , where String would be a key like this "2014/12/06".
LinkedHashMap<String, Value>
So, I can retrieve an item knowing the key, but what I'm looking for is a method to retrieve a list of the value which key matches partialy, I mean, how could I retrieve all the values of 2014?.
I would like to avoid solutions like, test every item in the list, brute-force, or similar.
thanks.
Apart from doing the brute-force solution of iterating over all the keys, I can think of two options :
Use a TreeMap, in which the keys are sorted, so you can find the first key that is >= "2014/01/01" (using map.getCeilingEntry("2014/01/01")) and go over all the keys from there.
Use a hierarchy of Maps - i.e. Map<String,Map<String,Value>>. The key in the outer Map would be the year. The key in the inner map would be the full date.
Not possible with LinkedHashMap only. If you can copy the keys to an ordered list you can perform a binary search on that and then do a LinkedHashMap.get(...) with the full key(s).
If you're only ever going to want to retrieve items using the first part of the key, then you want a TreeMap rather than a LinkedHashMap. A LinkedHashMap is sorted according to insertion order, which is no use for this, but a TreeMap is sorted according to natural ordering, or to a Comparator that you supply. This means that you can find the first entry that starts with 2014 efficiently (in log time), and then iterate through until you get to the first one that doesn't match.
If you want to be able to match on any part of the key, then you need a totally different solution, way beyond a simple Map. You'd need to look into full text searching and indexing. You could try something like Lucene.
You could refine a hash function for your values so that values with similar year would hash around similar prefixed hashes. That wouldn't be efficient (probably poor distribution of hashes) nor to the spirit of HashMaps. Use other map implementations such as TreeMaps that keep an order of your choice.
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).
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.