TreeMap Element does not removed - java

I created a map and then sort the values and put them in a TreeMap. But the problem is when I invoke the remove() method on Treemap, the element is not removed.
Does anybody have any idea what the problem is?
Here is my code:
Map<String , Double> map=new HashMap<String, Double>();
TreeMap<String, Double> sortedItems = sortMap(map);
sortedItems.remove("I put the key here as a string");
public TreeMap<String, Double> sortMap(Map<String, Double> map) {
HashMap<String, Double> map2 = new HashMap<String, Double>(map);
TreeMap<String, Double> sortedMap = SortByValue(map2);
return sortedMap;
}
public TreeMap<String, Double> SortByValue
(HashMap<String, Double> map) {
ValueComparator vc = new ValueComparator(map);
TreeMap<String, Double> sortedMap = new TreeMap<String, Double>(vc);
sortedMap.putAll(map);
return sortedMap;
}
class ValueComparator implements Comparator<String> {
Map<String, Double> map;
public ValueComparator(Map<String, Double> base) {
this.map = base;
}
public int compare(String a, String b) {
if (map.get(a) >= map.get(b)) {
return -1;
} else {
return 1;
} // returning 0 would merge keys
}

You need to return 0; when you expect a match. The way to solve this is to compare the key which it is otherwise a match. This way the same key will match, but only the same key.
public int compare(String a, String b) {
int cmp = -map.get(a).compareTo(map.get(b));
if (cmp == 0)
cmp = a.compareTo(b);
return cmp;
}
This way String keys which map to the same Double are seen as different iff they are different Strings.

returning 0 would merge keys
Returning 0 means the elements are equal. If you don't return 0, elements are never equal. Your TreeMap uses the given Comparator to put and remove. Your Comparator never identifies two keys as equal and therefore cannot remove anything.

Related

How can I have a treeMap which is sorted by value keep being sorted when I change elements?

I have a map of string keys and int values, I to sort them, and keep them sorted when I change values.
I tried using a treemap for the sorted pairs and a normal map for the unsorted paris so I can use it in the comparator, but after a one value passes the other I get a null expection, this is the defenition:
public static TreeMap<String, Long> countryData;
public static ValueComparator bvc;
public static void setCountryData(HashMap<String, Long> map){
bvc = new ValueComparator(map);
countryData = new TreeMap<String, Long>(bvc);
countryData.putAll(map);
System.out.println(Arrays.toString(countyNames));
System.out.println(countryData.values());
}
public static class ValueComparator implements Comparator<String> {
Map<String, Long> base;
public ValueComparator(Map<String, Long> base) {
this.base = base;
}
public int compare(String a, String b) {
if(base.get(a).equals(base.get(b))){
return 0;
}
if (base.get(a) > base.get(b)) {
return -1;
} else {
return 1;
}
}
}
this is how I change the values:
General.bvc.base.put(country, newValue);
General.countryData.put(country, newValue);
after one value passes another and I try to acces it, I get a null, how can I Do this?
How can I have a TreeMap which is sorted by value ..
You can't. They are sorted by key.
...
Irrelevant.

I am trying to sort a HashMap by Value, but the results i am getting is pretty awkward. Can anyone help me identify the reasons for it [duplicate]

This question already has answers here:
TreeMap sort by value
(13 answers)
Closed 7 years ago.
This is the code to sort HashMap by Value.
public class LongestChain
{
public static void main(String[] args)
{
String words[] = new String[]{"a","b", "c", "ca","ba","bca","bda","bdca"};
System.out.println(longestChainOfWords(words));
}
public static int longestChainOfWords(String words[])
{
Map<String, Integer> map = new HashMap<String, Integer>();
for(String a:words)
{
map.put(a, a.length());
}
System.out.println(map);
Map sortedMap = sortByValue(map);
System.out.println(sortedMap);
return sortedMap.size();
}
public static Map<String, Integer> sortByValue(Map<String, Integer> unsortedMap)
{
Map<String, Integer> sortedMap = new TreeMap<String, Integer>(new ValueComparator(unsortedMap));
sortedMap.putAll(unsortedMap);
return sortedMap;
}
}
class ValueComparator implements Comparator
{
Map<String, Integer> map;
public ValueComparator(Map<String, Integer> map)
{
this.map = map;
}
public int compare(Object keyA, Object keyB)
{
Comparable valueA = map.get(keyA);
Comparable valueB = map.get(keyB);
System.out.println(keyA+" keyA "); System.out.println(keyB+" keyB ");
return valueA.compareTo(valueB);
}
}
Output is like this. I was expecting 8 elements in sortedMap too. Why the behavior is like this?
{ca=2, bda=3, ba=2, b=1, c=1, a=1, bdca=4, bca=3}
{b=1, ca=2, bda=3, bdca=4}
4
Because you let the TreeMap think it sorts keys. And if the key is equal the no new value will be put inside. As you have 4 different values, so you can find 4 results in your list.
What you can do is improve the compare - method so equal values will be ordered by their keys:
class ValueComparator implements Comparator<String> {
Map<String, Integer> map;
public ValueComparator(final Map<String, Integer> map) {
this.map = map;
}
#Override
public int compare(final String keyA, final String keyB) {
final Integer valueA = this.map.get(keyA);
final Integer valueB = this.map.get(keyB);
System.out.println(keyA + " keyA ");
System.out.println(keyB + " keyB ");
final int compared = valueA.compareTo(valueB);
if (compared != 0) {
return compared;
} else {
return keyA.compareTo(keyB);
}
}
}

Sorting the Map in descending order of values [duplicate]

This question already has answers here:
Sort a Map<Key, Value> by values
(64 answers)
Closed 7 years ago.
I have been trying to sort the map in descending order of values but my existing code is sorting in descending order of keys. how do I sort in descending order of values?
My code:
System.out.println("Unsorted Map:" +merger);
Map<Integer, Double> Sortedmerger = SortByValue(merger);
System.out.println("Sorted Map: "+ Sortedmerger);
public static TreeMap<Integer, Double> SortByValue (Map<Integer, Double> map) {
ValueComparator vc = new ValueComparator(map);
TreeMap<Integer, Double> sortedMap = new TreeMap<Integer, Double>(Collections.reverseOrder());
sortedMap.putAll(map);
return sortedMap;
}
class ValueComparator implements Comparator<Double> {
Map<Integer, Double> map;
public ValueComparator(Map<Integer, Double> base) {
this.map = base;
}
public int compare(Double a, Double b) {
if (map.get(a) >= map.get(b)) {
return -1;
} else {
return 1;
} // returning 0 would merge keys
}
}
My output:
Unsorted Map:{1=0.53, 2=0.48, 23=0.54, 10=0.47}
Sorted Map: {23=0.54, 10=0.47, 2=0.48, 1=0.53}
Your map key type is Integer so you have to use Comparator<Integer> and your compare method should take integer inputs and by that Integer key you can get Double value by map.get(a) and map.get(b). and in TreeMap constructor you have to define comparator class which you have created.(i.e ValueComparator)
refer this code:
public static TreeMap<Integer, Double> SortByValue(Map<Integer, Double> map) {
ValueComparator vc = new ValueComparator(map);
TreeMap<Integer, Double> sortedMap = new TreeMap<Integer, Double>(vc);\\constructor should be vc which extends Comparator
sortedMap.putAll(map);
return sortedMap;
}
class ValueComparator implements Comparator<Integer> {
Map<Integer, Double> map;
public ValueComparator(Map<Integer, Double> base) {
this.map = base;
}
#Override
public int compare(Integer a, Integer b) {
// TODO Auto-generated method stub
if (map.get(a) >= map.get(b)) {
return -1;
} else {
return 1;
}
}
}

How to sort Map entries by values first, then by key and put the ordered keys in a List?

I have an HashMap :
private Map<String,Integer> matchesWonByTeam= new HashMap<String,Integer>();
I need to order those teams by matches won (value) and return an ArrayList with the names of the teams.
If any of those teams have the same amount of matches won they need to be alphabetically ordered.
What is the shortest and simplest way to do that using Collections and Comparators?
Here's some Java 8 for you.
final Comparator<Map.Entry<String, Integer>> byMatchesWon =
Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder());
final Comparator<Map.Entry<String, Integer>> byTeamName =
Comparator.comparing(Map.Entry::getKey);
final List<String> hasToBeReturned = matchesWonByTeam
.entrySet().stream()
.sorted(byMatchesWon.thenComparing(byTeamName))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
Note - inlining comparators would not work here, compiler will not be able to infer the proper implementation.
You could do it that way using functional programming :
final Map<String, Integer> map = new HashMap<>();
map.put("test", 1);
map.put("test1", 3);
map.put("test3", 4);
map.put("test2", 75);
map.put("a", 75);
map.put("test100", 100);
final List<String> test = map
.entrySet()
.stream()
.sorted((Entry<String, Integer> o1, Entry<String, Integer> o2) -> {
return o1.getValue().equals(o2.getValue()) ?
o1.getKey().compareTo(o2.getKey())
: o1.getValue().compareTo(o2.getValue());
})
.map(e -> e.getKey())
.collect(Collectors.toList());
for(String s : test)
System.out.println(s);
This example would output
test test1 test3 a test2 test100
Return the entry set, make a List, then use an anonymous Comparator implementation to sort the entries.
List<Entry<String,Integer>> matchesWonList = new ArrayList<Entry<String,Integer>>(matchesWonByTeam.entrySet());
Collections.sort(matchesWonList , new Comparator<Entry<String,Integer>>(){
//implement your comparator here.
});
This works:
Map<String,Integer> map = new HashMap<String,Integer>();
/*...fill map...*/
SortedSet<Map.Entry<String, Integer>> sortedSet = new TreeSet<>(new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) {
int res = e1.getValue().compareTo(e2.getValue());
if(res == 0)
return e1.getKey().compareTo(e2.getKey());
return res * -1;
}
});
sortedSet.addAll(map.entrySet());
List<String> list = new ArrayList<>();
for(Map.Entry<String, Integer> e: sortedSet)
list.add(e.getKey());
This is assuming you want the order to be from largest Integer to smallest Integer. If not, remove the * -1 when returning res.
matchesWonByTeam now will be a linkedHashMap which maintains the order.
matchesWonByTeam = matchesWonByTeam.entrySet()
.stream()
.sorted(
new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
if(o1.getValue() < o2.getValue()) {
return -1;
}
if(o1.getValue() > o2.getValue()) {
return 1;
}
return o1.getKey().compareTo(o2.getKey());
}
}
)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));

Using generics keys for methods returning hashmaps

I have a function that takes a map where keys can be of multiple types and values are always Integers. I need to perform operations on the values ignoring the keys and return the map at the end.
public Map<Sometype, Integer> doSomething(Map<Sometype, Integer> map, Integer total) {
Map<Sometype, Integer> result = new HashMap<Sometype, Integer>();
for (Sometype key : map.keySet()) {
result.put(key, map.get(key) * 2);
}
return result;
}
The map keys can be Integers, Booleans and Enums. Is there any way to apply generics so that I can use this method with any map type?
Yes. You can make your method generic on Sometype.
public <Sometype> Map<Sometype, Integer> doSomething(
Map<Sometype, Integer> map, Integer total) {
Map<Sometype, Integer> result = new HashMap<Sometype, Integer>();
for (Sometype key : map.keySet()) {
result.put(key, map.get(key) * 2);
}
return result;
}
That could also be written like
public <T> Map<T, Integer> doSomething(Map<T, Integer> map, Integer total) {
Map<T, Integer> result = new HashMap<T, Integer>();
for (T key : map.keySet()) {
result.put(key, map.get(key) * 2);
}
return result;
}

Categories