I have something like the following:
final SortedMap<Integer,List<Integer>> m = new TreeMap<Integer,List<Integer>>();
And I'd like to use google-guava to make this a multimap. However I don't see any implementation that provides a SortedMap holding an ArrayList. I only see HashMap+ArrayList implementation (ArrayListMultimap). Does the implementation that I want exist?
Guava has a TreeMultimap that stores both keys and values in sorted order. However, this uses a TreeSet for the values rather than a List so it may not quite be what you want here. In that case, Guava allows you to create a Multimap that works any way you want using one of the Multimaps.new*Multimap methods, such as Multimaps.newListMultimap. To make one that works like you describe, you'd just write this:
Map<Integer, Collection<Integer>> map = Maps.newTreeMap();
ListMultimap<Integer, Integer> m = Multimaps.newListMultimap(map,
new Supplier<List<Integer>>() {
public List<Integer> get() {
return Lists.newArrayList(); // assuming you want to use ArrayList
}
});
Here's how you can create that beast:
Multimap<Integer,Integer> multimap = Multimaps.newListMultimap(
Maps.<Integer, Collection<Integer>>newTreeMap(),
new Supplier<List<Integer>>() {
public List<Integer> get() {
return Lists.newArrayList();
}
});
Related
I have a List of programTypes:
List<String> programTypes = {ACF, VCX, IFL}
Note: This is a map hardcoded in code.
Here, I want to attach priorities to these programTypes:
ACF->priority=2, VCX->priority=1, IFL->priority=3
What data structure should I use? Priority Queues?
Also, now I have a list of inputProgramTypes: {ABC, VCX, IFL}
I want the output to be the winningProgramType: VCX
I can code it by iterating on inputProgramTypes and setting the winningProgramType if each next has a priority greater that the set one (Like finding max problem).
But I want to know if I can optimise? And how I can use streams to write code for same to make it look clean? I am new to streams and learning my way through it.
I suggest you use an enum with a parameter constructor.
Such, the method public static Map<ProgramType, Integer> getPrioMap() will elegantly and in a type-safe way return the data structure you need.
public enum ProgramType {
ACF(2), VCX(1), IFL(3);
private int prio;
private ProgramType(int prio) {
this.prio = prio;
}
public Integer getPriority() {
return prio;
}
public static Map<ProgramType, Integer> getPrioMap() {
return List.of(ProgramType.values()).stream()
.collect(Collectors.toMap(e -> e, e -> e.getPriority()));
}
}
Possibly, a simple Map will do fine:
public Map<String, Integer> buildMapOfPriorityProgramTypes() {
Map<String, Integer> priorityProgramTypes = new HashMap<>();
priorityProgramTypes.put("ACF", 2);
priorityProgramTypes.put("VCX", 1);
priorityProgramTypes.put("IFL", 3);
return priorityProgramTypes;
}
public String getTopPriorityType(Map<String, Integer> priorityTypes) {
return priorityTypes.entrySet().stream()
.min(Map.Entry.comparingByValue())
.get().getKey();
}
If you use Java 9 or newer, you may use shorter Map.of:
Map<String, Integer> priorityProgramTypes = Map.of(
"ACF", Integer.valueOf(2),
"VCX", Integer.valueOf(1),
"IFL", Integer.valueOf(3)
);
Use SortedMap interface and its implementation TreeMap:
SortedMap<Integer, List<String>> map = new TreeMap<>();
map.put(2, Collections.singletonList("ACF"));
map.put(1, Collections.singletonList("VCX"));
map.put(3, Collections.singletonList("IFL"));
The advantages are:
The keys are sorted, you can manage the order of them defining a Comparator in the constructor new TreeMap<>(comparator);. The order of processing from the sample above will be:
map.values().forEach(System.out::print);
// [VCX][ACF][IFL]
If more of the strings have the same priority, List<String> as the values of the map are more suitable.
Adding new priority (key) and value (List<String>) to the map will not break the sorted characteristics. For safe adding, I recommend Map::computeIfPresent .
I have a map of JSONObject and Integer. I want to sort it in an incremental order using its values, here is what I've done so far:
Map<JSONObject, Integer> unsortedMap = new HashMap<>();
unsortedMap.put(jsonObject2.getJSONObject(key),key1);
Are you sure you want to use an Object as a key in a hashmap? It's normal practice to use immutable values for keys. The slightest change in any of the elements of the JSONObject will change the hash value and you will be unable to get your info back out of the map.
What is the integer value of your map?
Only a suggestion but you may want to check out the Java API for collection and see if there is anything that better suits your needs. Java Collection API
In the past I have wanted a sorted list with no duplicates. I had to first write to a TreeMap and then write to a SortedSet to get the result I wanted. Not code efficient, but I couldn't achieve what I wanted any other way.
Not sure if this is the best option but could help:
public static Map<String, Integer> SortByKey(Map<String, Integer> map)
{
ArrayList<String> sortedKeys =
new ArrayList<String>(map.keySet());
Collections.sort(sortedKeys);
Map<String, Integer> sortedMap = new HashMap<>();
for (String x : sortedKeys)
sortedMap.put(map.get(x), Integer.parseInt(x));
return sortedMap;
}
I need to get the previous element of a LinkedHashMap.
I tried using the ListIterator because it has the previous() method. But the problem is ListIterator needs a List not a set.
ListIterator<Entry<String, Integer>> it = (ListIterator<Entry<String, Integer>>) unitsItems.entrySet().iterator();
I have to transform my entrySet into a list. So I tried this :
List entryList= new ArrayList (unitsItems.entrySet());
ListIterator<Entry<String, Integer>> it = (ListIterator<Entry<String, Integer>>) entryList.iterator();
I got this error:
java.util.ArrayList$Itr cannot be cast to java.util.ListIterator
Can anyone tell me the correct way to transform the set to a list and then use it in ListIterator?
Thank you.
As per request: Since you already have the list entryList you just need to call listIterator() on it to get what you want.
Btw, I'd add the generic type to the list as well: List<Entry<String, Integer>> = new ArrayList<>(unitsItems.entrySet());
If you're using Java 8, you can do this:
#Test
public void obtainListIterator() {
LinkedHashMap<String, String> test = new LinkedHashMap<>();
test.put("1", "a");
test.put("2", "a");
test.put("3", "a");
ListIterator<Map.Entry<String, String>> listIterator =
test
.entrySet()
.stream()
.collect(Collectors.toList())
.listIterator();
assertThat(listIterator.next().getKey()).isEqualTo("1");
assertThat(listIterator.previous().getKey()).isEqualTo("1");
}
However, the answer given by #Thomas is better than mine:
ListIterator<Map.Entry<String, String>> listIterator = new LinkedList(test.entrySet()).listIterator();
Using entrySet() is wrong since it's a method of HashMap and thus it does not contain any notion of list (thus your problems).
As you can see from the sources the linked list is implemented directly at the LinkedHashMap level.
That means that to do what you need (since the API do not supply a way) you'll need to subclass the LinkedHashMap and do it yourself.
I am trying to sort a hashmap based on its values,
The way I am doing this is separating the keyset and valueset of the hashmap into two arrayList
,then sorting the lists individually and then adding the values in a new haspMap after some comparison operations
but for some reason collection.reverse(LIST), won't sort the list in descending order
Here is my code:
public LinkedHashMap sortHashMapByValuesD(HashMap passedMap)
{
ArrayList <Integer>mapKeys = new ArrayList<Integer>(passedMap.keySet());
ArrayList <Double>mapValues= new ArrayList<Double>(passedMap.values());
Collections.reverse(mapValues);
Collections.reverse(mapKeys); //>>**Here the list won't sort for some reason**
LinkedHashMap<Integer, Double> sortedMap = new LinkedHashMap<Integer, Double>();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
//System.out.println(val);
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
Double comp1 =(Double)passedMap.get(key);
Double comp2 = (Double)val;
if (comp1==comp2){
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((Integer)key,(Double)val);
break;
}
}
}
return sortedMap;
}
Thanks in advance
HashMaps are hashed, not sorted. In particular, HashMap<K, V> does not implement the SortedMap<K, V> interface. If you want a map sorted by key, try TreeMap, or any other implementation of SortedMap.
Maps sorted by index are not commonly requested and not directly supported within rt.jar. You can't even call them SortedMaps, since a map sorted by values is (almost) certainly not sorted by keys. While you can implement a map that is sorted by value, you may find that a slightly different approach fits the bill while sticking to the philosphies of java's collections framework. Try creating a map-backed collection or iterator, that provides the ordering you require, and uses your original HashMap as its store.
A much simpler solution would be to
Set<Double> sortedSet = new TreeSet<Double>(yourPreferredComparator);
sortedSet.addAll(passedMap.values());
However you would lose any duplicated values with this solution.
I'm trying find a structure similar to a LinkedHashMap that sorts it by its value.
I'll need to be able to update the values.
I'll be checking the order very often, so I need a solution that avoids sorting the Map every time.
something like this:
DynamicSortedMap<String,Integer> map = new DynamicSortedMap<String,Integer>();
map.put("key1",4);
map.put("key2",3);
map.put("key3",6);
System.out.println("Map: "+map);
map.update("key1",1);
System.out.println("Update:"+map);
Output:
Map: {key3=6, key1=4, key2=3}
Update: {key3=6, key2=3, key1=1}
Is there any stucture that allows this?
If not, any ideas of how to do it?
Thanks for your help,
I think you are looking for something like TreeMap, which is sorted by key:
SortedMap<String, Integer> map = new TreeMap<String, Integer>();
Even though LinkedHashMap in fact could be a good base for this it's unfortunately very limited in manipulating the iteration order. I think with apache common-collections your better on.
class SortValueMap extends HashMap<String,Integer>{
#Override
public Set<Entry<String,Integer>> entrySet() {
List<Entry<String,Integer>> entries = new ArrayList<Entry<String,Integer>>(super.entrySet());
Collections.sort(entries, new Comparator<Entry<String,Integer>>(){
#Override
public int compare(Map.Entry<String,Integer> o1, Map.Entry<String,Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}});
return new LinkedHashSet<Entry<String,Integer>>(entries);
}
}
...
SortValueMap map = new SortValueMap();
map.put("key1",4);
map.put("key2",3);
map.put("key3",6);
map.put("key4",1);
System.out.println("Map: "+map);