I have created 2 HashMaps that store string values from two txt files. I am able to successfully print which values are duplicated amongst both Maps, however, I am having trouble determining how many times each values are duplicated.
Here is my code to identify duplicate values:
// find if hashmaps contain duplicate values
boolean val = wordsMap.keySet().containsAll(wordsMap1.keySet());
// create new entry for hashmap
for (Entry<String, Integer> str : wordsMap.entrySet()) {
System.out.println("================= " + str.getKey());
if(wordsMap1.containsKey(str.getKey())){
System.out.println("Map2 Contains Map 1 Key");
}
}
System.out.println("================= " + val);
Any suggestions? Thank you
I am thinking of something along the lines of
Map.values().equals(Map1.values()){
count++;
}
If I understand correctly, you want to find values which are common to two map objects. (Add null and/or other checks as required)
public static int duplicateCount(Map<String, Integer> m1, Map<String, Integer> m2) {
int count = 0;
Collection<Integer> m1Values = m1.values();
Collection<Integer> m2Values = m2.values();
for (Integer i : m1Values) {
if (m2Values.contains(i)) {
count++;
}
}
return count;
}
Here's a sample program have written based on my understanding of your doubt. It finds and displays the duplicate keys and also the duplicate values along with their frequencies of repetition. The logic is: To find the frequency, pass the duplicate element from map1 and the map2 as a parameter to countFrequency() method, which in turn will return the count of repetition.
package com.rahul.stackoverflow;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class DuplicateValHashMap {
public static void main(String[] args) {
Map<String, Integer> map1 = new HashMap<String, Integer>();
Map<String, Integer> map2 = new HashMap<String, Integer>();
map1.put("A", 1);
map1.put("B", 2);
map1.put("C", 3);
map1.put("D", 4);
map1.put("E", 5);
map2.put("A", 1);
map2.put("F", 2);
map2.put("G", 1);
map2.put("H", 3);
map2.put("B", 2);
for(Entry<String, Integer> entrySet : map1.entrySet()){
if(map2.containsKey(entrySet.getKey())){
System.out.println("Map2 contains keys of map1.");
System.out.println("Duplicate keys are : " + entrySet.getKey());
}
if(map2.containsValue(entrySet.getValue())){
System.out.println("Map2 contains values of map1.");
System.out.println("Duplicate values are : " + entrySet.getValue()+
" which is repeated " + countFrequency(map2, entrySet.getValue())+ " times.");
}
}
}
public static int countFrequency(Map<String, Integer> map, Integer value){
int count = 0;
for(Entry<String, Integer> entrySet : map.entrySet()){
if(value == entrySet.getValue()){
count++;
}
}
return count;
}
}
To get the number of duplicate keys between Maps,
public static int getDuplicateKeyCount(Map<?, ?> m1, Map<?, ?> m2) {
Set<?> tempSet = new HashSet<>(m1.keySet());
tempSet.retainAll(new ArrayList<>(m2.keySet()));
return tempSet.size();
}
To get the number of duplicate values between Maps,
public static int getDuplicateValueCount(Map<?, ?> m1, Map<?, ?> m2) {
List<?> tempList = new ArrayList<>(m1.values());
tempList.retainAll(m2.values());
return tempList.size();
}
To get a Map containing the frequency of the values of m1 in m2
public static <K, V> Map<V, Integer> getValueFrequencyMap(Map<K, V> m1, Map<K, V> m2) {
Map<V, Integer> freq = new HashMap<>();
Collection<V> col = m2.values();
for(V val : m1.values()) {
freq.put(val, Collections.frequency(col, val));
}
return freq;
}
Related
I'm trying to convert the keys of a Map to Values of another Map, but finally only one key was return as Value. What was the problem?
when the program excuted I got different Result
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class KeystoValues {
public static void KtoV(Map<Double, Integer> Key) {
Map<Double, Integer> List = new HashMap<Double, Integer>();
Map<Integer, Double> KeystoV = new HashMap<Integer, Double>();
System.out.println("List Map\n");
List.putAll(Key);
for(Map.Entry<Double, Integer> val : List.entrySet()) {
System.out.println(val.getKey() + "," + val.getValue());
}
for(int h = 1; h<=List.size(); h++)
for(Map.Entry<Double, Integer> convert : List.entrySet()) {
Double j = convert.getKey();
KeystoV.put(h, j);
}
System.out.println("\nSet of keys in List Map now converted to set "
+ "of Values and stored to KeystoV Map\n\nKeystoV Map\n");
for(Map.Entry<Integer, Double> converted : KeystoV.entrySet()) {
System.out.println(converted.getKey() + "," + converted.getValue());
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Integer> Value = new ArrayList<Integer>();
Map<Double, Integer> Key = new HashMap<Double, Integer>();
Key.put(45.0,1);
Key.put(40.0,2);
Key.put(23.0,2);
Key.put(25.0,3);
Key.put(0.0,1);
KtoV(Key);
}
}
List Map
0.0,1
25.0,3
40.0,2
45.0,1
23.0,2
Set of keys in List Map now converted to set of Values and stored to KeystoV Map
KeystoV Map
1,23.0
2,23.0
3,23.0
4,23.0
5,23.0
The problem with your code is this nested for loop:
for(int h = 1; h<=List.size(); h++)
for(Map.Entry<Double, Integer> convert : List.entrySet()) {
Double j = convert.getKey();
KeystoV.put(h, j);
}
If you debug it, then you'll see that you are always putting the last iterated value of List.entrySet() as the value of all keys.
Try changing it to:
int index = 1;
for (Map.Entry<Double, Integer> convert : List.entrySet()) {
KeystoV.put(index, convert.getKey());
index++;
}
You have to use a list for the second map values because some of your values could appear twice and that would result in duplicate keys which maps can't support.
Collectors.groupingBy creates a map using a supplied key
Collectors.mapping gets the key as the value for entry into the value which is a list of doubles.
Try it like this.
Map<Double, Integer> map = Map.of(2.0, 1, 3.0, 1, 8.0, 5, 9.0, 7, 4.0, 7);
Map<Integer, List<Double>> keystoV = map.entrySet().stream().collect(Collectors.groupingBy(Entry::getValue,
Collectors.mapping(Entry::getKey, Collectors.toList())));
map.entrySet().forEach(System.out::println);
System.out.println();
keystoV.entrySet().forEach(System.out::println);
prints
9.0=7
8.0=5
2.0=1
3.0=1
4.0=7
1=[2.0, 3.0]
5=[8.0]
7=[9.0, 4.0]
Here is a loop version using the Map.computeIfAbsent method.
if key is absent, create a list for that key.
it also returns the list so the new value (old key) many be added to the list.
keystoV.entrySet().forEach(System.out::println);
Map<Integer, List<Double>> result = new HashMap<>();
for(Entry<Double, Integer> e : map.entrySet()) {
result.computeIfAbsent(e.getValue(), v->new ArrayList<>()).add(e.getKey());
}
result.entrySet().forEach(System.out::println);
prints
1=[2.0, 3.0]
5=[8.0]
7=[9.0, 4.0]
So i was wondering how and if it was possible using Hashmaps, one containing only strings and the other containing a similar string key but a float value, to compare them and then from that comparison print out the amount of similar values in the first hashmap, and then the float from the second hashmap added together when their keys/values line up. Example below that should clarify what i mean and to do this dynamically.
CODE
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, Float> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", (float) 19.95);
h2map.put("order2", (float) 19.95);
h2map.put("order3", (float) 39.9);
Set <String> singles = new HashSet<>(h2map.values());
if(h2map.keySet().equals(hmap.keySet())) {
// below prints out the states and amount of the states but how can i get the float values from hmap to be added together for the similar states and printed with their respective state?
for(String element : singles) {
System.out.println(element + ": " + Collections.frequency(hmap.values(), element));
}
}
Current Output
pending: 2
cancelled: 1
Desired Output
pending: 2 $59.85
cancelled 1 $19.95
Is this what you want?
public static void main(String[] args) {
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, Float> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", 19.95f);
h2map.put("order2", 19.95f);
h2map.put("order3", 39.9f);
Map<String, DoubleSummaryStatistics> grouping = hmap
.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.summarizingDouble(e -> h2map.get(e.getKey()))));
grouping.forEach((key, value) -> System.out.println(key + ": " + value.getCount() + " " + value.getSum()));
}
Note that there is no summarizing statistics collector for BigDecimal and this code works only with Float or Double. But for money calculations better use BigDecimal. It's possible to implement the custom collector if needed )
I have replaced the use of Float with BigDecimal for better accuracy. Also I used two maps, one for holding the summed value and the other for count:
public static void main(String[] args) {
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, BigDecimal> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", new BigDecimal("19.95"));
h2map.put("order2", new BigDecimal("19.95"));
h2map.put("order3", new BigDecimal("39.9"));
//Map for holding sum
HashMap<String, BigDecimal> sum = new HashMap<>();
for(String key : h2map.keySet()){
if(hmap.get(key) != null){
String value = hmap.get(key);
if(sum.get(value) == null){
sum.put(value, h2map.get(key));
}else{
sum.put(value, (sum.get(value).add(h2map.get(key))));
}
}
}
//Map for holding count
HashMap<String, BigDecimal> countMap = new HashMap<>();
for(Iterator<Map.Entry<String, BigDecimal>> itr = sum.entrySet().iterator(); itr.hasNext(); ){
Map.Entry<String, BigDecimal> entry = itr.next();
String key = entry.getKey();
int count = Collections.frequency(hmap.values(), key);
countMap.put((key + count), sum.get(key));
itr.remove();
}
//For GC
sum = null;
countMap.forEach((k, v) -> System.out.println(k + " " + v));
}
This question already has answers here:
Sort a Map<Key, Value> by values
(64 answers)
Closed 7 years ago.
Forgive me if it seems simple but I couldn't figure it out easily. I thought about using a loop but was wondering if anybody knows an easier way: I have:
Map<String, Integer> map = new HashMap<>();
map.put("ClubB", 1);
map.put("ClubA", 2);
map.put("ClubC", 2);
map.put("ClubD", 2);
map.put("ClubE", 3);
map.put("ClubF", 2);
map.put("ClubG", 2);
I need to get keys or values at specific index in my tests. For example I need to get the key and value at index 3 etc. The reason is that I use a comparator and sort the Map and would like to show that the value at a specific index has changed.
Thanks for any ideas.
UPDATE:
I used:
HashMap leagueTable = new HashMap();
Map<String, Integer> map = sortByValues(leagueTable);
public <K extends Comparable<K>, V extends Comparable<V>> Map<K, V> sortByValues(final Map<K, V> map) {
Comparator<K> valueComparator = new Comparator<K>() {
public int compare(K k1, K k2) {
int compare = map.get(k2).compareTo(map.get(k1));
if (compare == 0) {
return k1.compareTo(k2); // <- To sort alphabetically
} else {
return compare;
}
}
};
Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
sortedByValues.putAll(map);
return sortedByValues;
}
I then used aloop to print out values:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println( entry.getKey() + ", " + entry.getValue() );
}
Ended up using a for loop and comparing with what I already had added to the Map:
HashMap<String, Integer> map = new HashMap<>();
map.put("ClubD", 3);
map.put("ClubB", 1);
map.put("ClubA", 2);
map.put("ClubC", 2);
map.put("ClubE", 2);
map.put("ClubF", 2);
map.put("ClubG", 2);
Map<String, Integer> mapResult = instance.sortByValues(map);
String expectedResultKey = "ClubB";
int expectedResultValue = 1;
String resultKey = "";
int resultValue = 0;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
resultKey = entry.getKey();
resultValue = entry.getValue();
}
assertSame(expectedResultKey, resultKey);
HashMap's don't have indices. They just store data in key-value pairs.
Instead of map being a Map, why don't you use a 2D array? (And give it a more appropriate name)
String[][] array = new String[3][3];
array[3] = new String[] { "ClubD" };
array[1] = new String[] { "ClubB" };
array[2] = new String[] { "ClubA", "ClubC", "ClubE", "ClubF", "ClubG" };
System.out.println(array[3][0]);
and then if you wanted to loop through that array, you would just do:
for (int a = 0; a < array.length; a++)
for (int b = 0; b < array[a].length; b++)
if (array[a][b] != null)
System.out.println("array["+a+"]["+b+"] is: "+array[a][b]);
I have a few methods that I was given from here a few days ago to help me with my scores. Basically when the game ends I want to get the top players with the best scores and put them into round 2, so if there were 8 players I want it to split them in half and the top half being the ones with the best scores, the methods below work fine but if there were 3 players in the game it would only take the top one instead of 2, 5 players in the game it would only take the top 2 instead of 3.
How do I get the top half with the highest scores and if say 2 players have the same score, then both of them would go through. For example:
Player 1 = 1;
Player 2 = 10;
Player 3 = 10;
Player 4 = 25;
Methods below would return player 4 and 3 but player 2 also has 10 points so he should be in it too.
public static Map<String, Integer> getTopHalf(Map<String, Integer> map){
Map<String, Integer> sorted = sortByComparator(map);
Map<String, Integer> out = new HashMap<String, Integer>();
Iterator<Entry<String,Integer>> it = sorted.entrySet().iterator();
for(int i = 0; i<map.size()/2; i++){
Entry<String, Integer> e = it.next();
out.put(e.getKey(), e.getValue());
}
return out;
}
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap){
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
Collections.sort(list, new Comparator<Entry<String, Integer>>(){
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2){
return o2.getValue().compareTo(o1.getValue());
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list){
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
public static void printMap(Map<String, Integer> map){
for (Entry<String, Integer> entry : map.entrySet()){
System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue());
}
}
And for testing I use this:
Map<String, Integer> unsortMap = new HashMap<String, Integer>();
unsortMap.put("B", 89);
unsortMap.put("A", 45);
unsortMap.put("f", 43);
unsortMap.put("j", 47);
unsortMap.put("h", 41);
System.out.println("After sorting descindeng order and deleting half......");
Map<String, Integer> half = getTopHalf(unsortMap);
printMap(half);
List<Integer> achievedPoints = new ArrayList<>(allPlayers.values());
Collections.sort(achievedPoints); /*- from few points to many points */
int requiredScore = achievedPoints.get(achievedPoints.size());
Map<String, Integer> playersInNextRound = new HashMap<>();
for (Map.Entry<String, Integer> player : allPlayers.entrySet()) {
if (player.getValue() >= requiredScore) {
playersInNextRound.put(player.getKey(), player.getValue());
}
}
I'm trying to get results HashMap sorted by value.
This is HashMap's keys and values:
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
I try to get results like this:
1 = can
2 = selin
4 = burak
5 = ertu
Here is my code:
import java.util.*;
public class mapTers {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
Integer dizi[] = new Integer[map.size()];
Set anahtarlar = map.keySet();
Iterator t = anahtarlar.iterator();
int a = 0;
while (t.hasNext()) {
dizi[a] = map.get(t.next());
a++;
}
Arrays.sort(dizi);
for (int i = 0; i < map.size(); i++) {
while (t.hasNext()) {
if (dizi[i].equals(map.get(t.next()))) {
System.out.println(dizi[i] + " = " + t.next());
}
}
}
}
}
You can sort the entries as follows (but note this won't sort the map itself, and also HashMap cannot be sorted) -
List<Map.Entry<String, Integer>> entryList = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
Every time that you call t.next(), the iterator's pointer is moved forward. Eventually, the iterator reaches the end. You need to reset the iterator. Also, calling t.next() twice moves the pointer twice.
Here's my solution:
import java.util.*;
public class mapTers
{
public static void main(String[] args)
{
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
Integer dizi[] = new Integer[map.size()];
Set anahtarlar = map.keySet();
Iterator t = anahtarlar.iterator();
int a = 0;
while (t.hasNext())
{
dizi[a] = map.get(t.next());
a++;
}
Arrays.sort(dizi);
for (int i = 0; i < map.size(); i++)
{
t = anahtarlar.iterator();
while (t.hasNext())
{
String temp = (String)t.next();
if (dizi[i].equals(map.get(temp)))
{
System.out.println(dizi[i] + " = " + temp);
}
}
}
}
}
You cannot do that from a Map. At least not directly.
Retrieve the keys/entries, get all the map data in a more suitable structure (hint: a class that encapsulates both attributes and is is stored in a sortable (hint2: SortedSet, List)) and sort.
Do not forget to extend Comparable (and implement compareTo) or, otherwise, create a Comparator.
This is one of the solutions take from: https://stackoverflow.com/a/13913206/1256583
Just pass in the unsorted map, and you'll get the sorted one.
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap, final boolean order) {
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (order) {
return o1.getValue().compareTo(o2.getValue());
}
else {
return o2.getValue().compareTo(o1.getValue());
}
}
});
// Maintaining insertion order with the help of LinkedList
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
To print, do a simple iteration over the entry set:
public static void printMap(Map<String, Integer> map) {
for (Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue());
}
}
You probably have the wrong data structure for this problem. Either:
Reverse the map so the integers are the keys and the words the values and make the map a SortedMap, or
Use a bidirectional map as provided by libraries like Google Guava.
Reversed Map
private final SortedMap<Integer, String> TRANSLATIONS;
static {
SortedMap<Integer, String> map = new TreeMap<>();
map.put(1, "can");
// ...
TRANSLATIONS = Collections.unmodifiableSortedMap(map);
}
Guava BiMap
private final BiMap TRANSLATIONS =
new ImmutableBiMap.Builder<String, Integer>()
.put("ertu", 5);
.put("burak", 4);
.put("selin", 2);
.put("can", 1);
.build();
Then, iterate over a sorted version of the key set or value set as needed. For example,
TRANSLATIONS.inverse.get(4); // "burak"
I'm just curious. What language are your strings in?