Java hashmap iterator - java

I want to make the method removeValue( "a", "x").
It must delete all keys and values between the letters. For example:
{1=a,2=b,3=c,5=x} ->> {1=a,5=x}
I tried with equals and iterator but I don't know how to write it.
public class CleanMapVal {
public static void main(String[] args) throws Exception {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "a");
map.put("2", "b");
map.put("3", "c");
map.put("4", "w");
map.put("5", "x");
System.out.println( map );
for (Iterator<String> it = map.keySet().iterator(); it.hasNext();)
if ("2".equals(it.next()))
it.remove();
System.out.println(map);
}
public static <K, V> void removeValue(Map<K, V> map) throws Exception {
Map<K, V> tmp = new HashMap<K, V>();
for (Iterator<K> it = map.keySet().iterator(); it.hasNext();) {
K key = it.next();
V val = map.get(key);
if (!tmp.containsValue(val)) {
tmp.put(key, val);
}
}
map.clear();
for (Iterator<K> it = tmp.keySet().iterator(); it.hasNext();) {
K key = it.next();
map.put((K) tmp.get(key), (V) key);
}
}
}

Try the following code.I'm using treemap to maintain the order and then iterating to remove the elements.
Map<Integer, String> map = new TreeMap<Integer, String>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
map.put(4, "w");
map.put(5, "x");
ArrayList<Integer> intList = new ArrayList<Integer>();
for (Iterator<Integer> it = map.keySet().iterator(); it.hasNext();) {
int key = 0;
if (it.next() == 1) {
while(true) {
key = it.next();
if(key==5)break;
intList.add(key);
}
}
}
//removing from the map in separate loop to avoid concurrent modification exception
for (int i : intList) {
map.remove(i);
}
System.out.println(map.size()); //2

First of all, a HashMap never keeps the orders of the Object which are put in it. So you need to use LinkedHashMap which maintains its insertion order.
For removal of Object you need to make use of Iterator
Map testMap = new LinkedHashMap<Integer, String>(); If your key is of any other type except Integer change it accordingly.
So for your requirement, you can use the below code :-
public static void testKey(Map<Integer, String> testMap, String startValue,
String endValue) {
if(!testMap.containsValue(startValue) || !testMap.containsValue(endValue))
return; // if start/end value is not present in Map then no change at all
Iterator<Map.Entry<Integer, String>> iter = testMap.entrySet()
.iterator();
boolean deleteFlag = false;
while (iter.hasNext()) {
Map.Entry<Integer, String> entry = iter.next();
if (endValue.equalsIgnoreCase(entry.getValue())) {
deleteFlag = false;
}
if (deleteFlag)
iter.remove();
if (startValue.equalsIgnoreCase(entry.getValue())) {
deleteFlag = true;
}
}
}
public static void main(String[] args) {
Map m = new LinkedHashMap<Integer, String>();
m.put(1, "a");
m.put(2, "b");
m.put(3, "c");
m.put(5, "x");
System.out.println("before : "+m);
removeValue(m, "a", "x");
System.out.println("after : "+m);
}
Output
before : {1=a, 2=b, 3=c, 5=x}
after : {1=a, 5=x}

Using an Iterator allows you to remove entries on the fly.
public void removeRange(Map<Integer, String> map, String from, String to) {
// Walk each entry.
for (Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator(); it.hasNext();) {
// What is the value?
String v = it.next().getValue();
if (v.compareTo(from) > 0 && v.compareTo(to) < 0) {
// In the specified range! Remove it.
it.remove();
}
}
}
public void test() {
Map<Integer, String> map = new HashMap<>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
map.put(4, "w");
map.put(5, "x");
System.out.println("Before:" + map);
removeRange(map, "a", "x");
System.out.println("After:" + map);
}
prints
Before:{1=a, 2=b, 3=c, 4=w, 5=x}
After:{1=a, 5=x}
If you are using Java 8 you can also stream and filter a Map.
public <K, V> Map<K, V> filter(Map<K, V> map, Predicate<Map.Entry<K, V>> filter) {
return map.entrySet()
.stream()
// Filter out the unwanted ones.
.filter(filter)
// Fold back into a new Map.
.collect(Collectors.toMap(
(Map.Entry<K, V> e) -> e.getKey(),
(Map.Entry<K, V> e) -> e.getValue()));
}
public Map<Integer, String> removeRangeWithStream(Map<Integer, String> map, String from, String to) {
return filter(map,
(Map.Entry<Integer, String> e) -> e.getValue().compareTo(from) <= 0 || e.getValue().compareTo(to) >= 0);
}

Related

looping through iterator returns the same value

I have the issue that my loop does not break and returns the same value
public Map<String, String> getKeysByValue(Map<String, Map<String, Peple>> map, Collection<Peple> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
while (value.iterator().hasNext()) {
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
String verified = value.iterator().next().gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), value.iterator().next().getName());
}
}
}
The problem here is that the same value kets put in the map for every key (value.iterator().next().getName()) always returns the same string
I think the below would be a correct approach for your problem:
public Map<String, String> getKeysByValue(Map<String, Map<String, Peple>> map, Collection<Peple> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
Iterator<People> peopleIterator = value.iterator();
while (peopleIterator.hasNext()) {
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
People people = peopleIterator.next();
String verified = people.gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), people.getName());
}
}
}
You need to store the iterator in a variable.
Consider below simple code :
Collection<String> strings = new ArrayList<>();
strings.add("value1");
strings.add("value2");
strings.add("value3");
strings.add("value4");
while (strings.iterator.hasNext())
{
System.out.println(strings.iterator.next());
}
This will run infinitely and will only print value1, but if you modify the code as below :
Collection<String> strings = new ArrayList<>();
strings.add("value1");
strings.add("value2");
strings.add("value3");
strings.add("value4");
Iterator<String> stringIterator = strings.iterator();
while (stringIterator.hasNext())
{
System.out.println(stringIterator.next());
}
It runs smooth.
You can learn more about iterator here : https://www.geeksforgeeks.org/how-to-use-iterator-in-java/
ALso, I think as you are calling iterator twice without checking hasNext() on the second call, it can throw java.util.NoSuchElementException
You are calling next() twice on that iterator. That moves it ahead and picks up the name of the next People, which might not be verified.
I believe you just want to get the name if it's a verified Peple?
while (value.iterator().hasNext()) {
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
Peple nextPeple = value.iterator().next();
String verified = nextPeple.gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), nextPeple.getName());
}
}
}
}
Every time you call value.iterator() new Iterator object is created from scratch, pointing to a first element. To avoid it, store first result of calling it into local variable.
Iterator<Peple> it = value.iterator();
while(it.hasNext()){
// your remaiing code
}
This code works fine with the below input:
import java.util.*;
public class Test {
public static void main(String[] ar){
Map<String, People> entry1 = new HashMap<String , People>();
People people1 = new People("true","name1");
People people2 = new People("false","name2");
People people3 = new People("true","name3");
entry1.put("user1", people1);
entry1.put("user2", people2);
entry1.put("user3", people3);
Map<String, People> entry2 = new HashMap<String , People>();
People people4 = new People("true","name1");
People people5 = new People("false","name2");
People people6 = new People("true","name3");
entry2.put("user1", people4);
entry2.put("user2", people5);
entry2.put("user3", people6);
Map<String, Map<String, People>> map2 = new HashMap<String, Map<String,
People>>();
map2.put("set1",entry1);
map2.put("set2",entry2);
Collection<People> strings = new ArrayList<>();
strings.add(people1);
strings.add(people6);
strings.add(people5);
strings.add(people3);
strings.add(people2);
getKeysByValue(map2, strings);
}
public static Map<String, String> getKeysByValue(Map<String, Map<String, People>> map, Collection<People> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
Iterator<People> it = value.iterator();
while (it.hasNext()) {
People people = it.next();
for (Map.Entry<String, Map<String, People>> entry : map.entrySet()) {
for (Map.Entry<String, People> entry1 : entry.getValue().entrySet()) {
String verified = people.getVerified();
System.out.println(verified);
System.out.println("Key : "+entry1.getKey() +" Value : "+entry1.getValue().getVerified());
if (verified.equals(entry1.getValue().getVerified())) {
stringStringMap.put(entry1.getKey(), people.getName());
}
}
}
}
System.out.println(stringStringMap);
return stringStringMap;
}
}
People.java
public class People {
String verified;
public People(String verified, String name){
this.verified = verified;
this.name = name;
}
public String getVerified() {
return verified;
}
public String getName() {
return name;
}
String name;
}
Try this:
public Map<String, String> getKeysByValue(Map<String, Map<String, Peple>> map, Collection<Peple> value) {
Map<String, String> stringStringMap = new HashMap<>();
int count = 0;
Iterator<Peple> iterator = value.iterator();
while (iterator.hasNext()) {
Peple p = iterator.next();
for (Map.Entry<String, Map<String, Peple>> entry : map.entrySet()) {
for (Map.Entry<String, Peple> entry1 : entry.getValue().entrySet()) {
String verified = p.gerVerfied();
if (verified.equals("true")) {
stringStringMap.put(entry1.getKey(), p.getName());
}
}
}
}
}

Want to concatenate Value of one map to key of another map

I want to concatenate to the value of one map to key of another map and add them into list.
Compare value on basis of key of first map to value of another map.
e.g:
map1= {37=core__error_code_based, 153=core__app_dialog, 123=core__date}
map2={copy_2=37,button_back=37,button_cancel=153,button_confirm=153}
My approach is in first loop i get the key of map1 and then in second loop iterate the map2 values on basis map1 key.
So that I get the value of map1 and key of map2 and later concatenate in string.
List<String> finalKey=new ArrayList<>();
Iterator<Map.Entry<String,String>> entrySet=map1.entrySet().iterator();
Iterator<Map.Entry<String,String>> pageKey=map2.entrySet().iterator();
while(entrySet.hasNext()){
Map.Entry<String,String> entry = entrySet.next();
Map.Entry<String,String> pageValue = pageKey.next();
while(entry.getKey()==pageValue.getValue()){
finalKey.add(entry.getValue()+"__"+pageValue.getKey());
}
}
I had tried using iterator and entryset to iterate through the both map but not succeed
{core__error_code_based__copy_2,core__error_code_based__button_back,core__app_dialog__button_confirm,core__app_dialog__button_cancel}
Well i achieved this using
public class translatekeyName {
static List<String> finalString = new ArrayList<>();
public static Map<String, String> initialMap() {
Map<String, String> map1 = new HashMap<>();
map1.put("37", "core__error_code_based");
map1.put("153", "core__app_dialog");
return map1;
}
public static Map<String, String> secondMap() {
Map<String, String> map2 = new HashMap<>();
map2.put("copy_2", "37");
map2.put("button_back", "37");
map2.put("button_cancel", "153");
map2.put("button_confirm", "153");
return map2;
}
public List<String> concatenateString(Map page, Map source) {
Map<String, String> moduleKey = page;
Map<String, String> pageKey = source;
List<String> temp;
Iterator<Map.Entry<String, String>> entrySet = page.entrySet().iterator();
Iterator<Map.Entry<String, String>> pageKeyset = source.entrySet().iterator();
for (String value : moduleKey.keySet()) {
temp = getallKeys(source, value);
String tempValue = moduleKey.get(value);
for (int i = 0; i < temp.size(); i++) {
tempValue += "__" + temp.get(i);
finalString.add(tempValue);
}
}
return finalString;
}
static <K, V> List<K> getallKeys(Map<K, V> mapOfWords, V value) {
List<K> keylist = null;
if (mapOfWords.containsValue(value)) {
keylist = new ArrayList<>();
for (Map.Entry<K, V> entry : mapOfWords.entrySet()) {
if (entry.getValue().equals(value)) {
keylist.add(entry.getKey());
}
}
}
return keylist;
}
public static void main(String[] args) {
translatekeyName obj = new translatekeyName();
obj.concatenateString(initialMap(), secondMap());
System.out.println(finalString);
}
}

How to "print" a HashMap in a Hashmap in Java/Android

I want to "print" a Hashmap<String, Integer> (let's say Alpha) in a Hashmap<String, Hashmap<String, Integer>> (Beta) and I say "print" because I don't want the "printed" Alpha to change when I re-use Alpha.
For example:
class scratch_2 {
public static void main(String[] args) {
HashMap<String, Integer> Alpha = new HashMap<>();
HashMap<String, HashMap<String, Integer>> Beta = new HashMap<>();
Beta.put("A1", Alpha);
Beta.put("B2", Alpha);
Alpha.put("A", 1);
Alpha.put("B", 2);
System.out.println(Beta); --->print1
Alpha.clear();
System.out.println(Beta); ---->print2
}
}
Result of print1: {A1={A=1, B=2}, B2={A=1, B=2}}
Result of print2: {A1={}, B2={}}
How to set the Beta.put() so that when Alpha is cleared, Beta remains the same?
Here is what you can do to reset a nested HashMap. The value is removed on line 22 and then added back as a new inner hashmap instance. Again, I loop through containingMap and the innerMap getting each map. Once I have a value to reset I call the reset function.
import java.util.*;
import java.lang.*;
public class Collections {
public HashMap<String, HashMap<String, Integer>>
createMap(String beta, String alpha, int m, HashMap<String,
Integer> innerStructure, HashMap<String, HashMap<String,
Integer>> containingStructure) {
while(m>0) {
innerStructure.put(beta, m);
m--;
}
containingStructure.put(alpha, innerStructure);
return containingStructure;
}
public void reset(HashMap<String, HashMap<String, Integer>>
map, int x) {
HashMap<String, Integer> betaMap = new HashMap<String, Integer>();
for(Map.Entry<String,HashMap<String,Integer>> entry: map.entrySet()) {
System.out.println("Key before is:" + entry.getKey());
if(entry.getValue() instanceof Map) {
for(Map.Entry<String, Integer> mapEntry: entry.getValue().entrySet()) {
if(mapEntry.getValue() == x) {
entry.getValue().remove(x);
map.put(entry.getKey(), betaMap);
}
}
}
}
}
public void print(HashMap<String, HashMap<String, Integer>> map) {
for(Map.Entry<String,HashMap<String,Integer>> entry: map.entrySet()) {
System.out.println("Key is:" + entry.getKey());
if(entry.getValue() instanceof Map) {
for(Map.Entry<String, Integer> mapEntry: entry.getValue().entrySet()) {
System.out.println(mapEntry.getKey());
}
}
}
}
public static void main(String[] args) {
Collections collections = new Collections();
HashMap<String, Integer> innerStructure = new HashMap<>();
HashMap<String, HashMap<String, Integer>> containingStructure = new HashMap<>();
containingStructure = collections.createMap("B1", "A1", 4, innerStructure, containingStructure);
collections.reset(containingStructure, 2);
collections.print(containingStructure);
}
}
It really doesn't change the Beta with put it is a matter of evaluating each entry and making sure it is a new HashMap type being used in it's place. I think this should help.
As #Andreas said, I should have created a new instance of Alpha by assigning it like Alpha = new HashMap<>(); when I no longer needed it. I can then re-use it without affecting Beta.

Get k highest values from HashMap

In the code I have posted below, I need to remove the duplicates from the HashMap (the highest alphabetical value gets to stay in the map) and print the keys of the k highest values after the duplicates are removed. How do I do this? I tried with a HashSet but I am pretty clueless.
public ArrayList<String> mostOften(int k)
{
ArrayList<String> lista = new ArrayList<String>();
HashMap<String,Integer> temp = new HashMap<String, Integer>();
for(String it : wordList)
{
if(temp.containsKey(it))
temp.put(it, temp.get(it)+1);
else
temp.put(it, 1);
}
temp = sortByValues(temp);
Set<Integer> set = new HashSet<Integer>(temp.values());
System.out.println(set);
return lista;
}
private static HashMap sortByValues(HashMap map)
{
List list = new LinkedList(map.entrySet());
Collections.sort(list, new Comparator()
{
public int compare(Object o1, Object o2)
{
return ((Comparable)((Map.Entry) (o1)).getValue()).compareTo(((Map.Entry) (o2)).getValue());
}
});
HashMap sortedHashMap = new LinkedHashMap();
for (Iterator it = list.iterator(); it.hasNext();)
{
Map.Entry entry = (Map.Entry) it.next();
sortedHashMap.put(entry.getKey(), entry.getValue());
}
return sortedHashMap;
}
If you are trying to do a frequency count of words you are heading down the wrong road. Java 8 does this much easier and cleaner.
You need these imports
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
The code
public static void main(String[] args) {
printTopWords(Arrays.asList("Hello World Hello , Bye World".split(" ")), 2);
}
public static void printTopWords(List<String> words, int limit) {
// using the Stream API
words.stream()
// create a map of words with the count of those words
.collect(Collectors.groupingBy(w -> w, Collectors.counting()))
// take that map as a stream of entries
.entrySet().stream()
// sort them by count in reverse order
.sorted(Comparator.comparing(Map.Entry<String, Long>::getValue).reversed())
// limit the number to get top Strings
.limit(limit)
// keep just the key ie. drop the count.
.map(Map.Entry::getKey)
// print them
.forEach(System.out::println);
}
prints
Hello
World
If you are not familiar with java 8 streams and lambdas then below answer would be helpful to you :
public class Java7Way {
public static void main(String[] args) {
Map<String, Integer> myMap = new HashMap<>();
myMap.put("A", 20);
myMap.put("A", 38);
myMap.put("B", 40);
myMap.put("K", 23);
System.out.println(sortByValue(myMap,2).toString());
}
public static <K, V extends Comparable<? super V>> Map<K, V>
sortByValue(Map<K, V> map,int limit) {
List<Map.Entry<K, V>> list
= new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
#Override
public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
}
.reversed()//to arrange it in decending order
);
Map<K, V> result = new LinkedHashMap<>();//maintains the order which the entries were put into the map
for (Map.Entry<K, V> entry : list) {
if (limit == 0) {
break;
}
result.put(entry.getKey(), entry.getValue());
limit--;
}
return result;
}
}
Out-put :
{B=40, A=38}
I recommend using TreeBidiMap from Apache Commons Collection. In this structure all keys and all values sorted according to the natural order for the key's and value's classes.
For your code:
BidiMap<String,Integer> temp = new TreeBidiMap<String, Integer>();
for(String it : wordList)
{
if(temp.containsKey(it))
temp.put(it, temp.get(it)+1);
else
temp.put(it, 1);
}
// print values unsing natural sorting in reverse order
BidiMap inverse = temp.inverseBidiMap();
for (MapIterator it = inverse.mapIterator(); it.hasPrevious();) {
String k = it.next();
Integer s = it.getValue();
System.out.printLn(s + " = " + k);
}

Print first 40 elements in a list ordered by value

I still am not getting the top 40 le t me show you my code:
Map<String, Integer> doubleCount= new HashMap<>();
SortedMap<String,Integer> newMap= new TreeMap<>(doubleCount);
Map<String,Integer> newDouble40 = newMap.headMap("40");
System.out.println(newDouble40);
this is giving me an empty list, and more than that it does not sort it.... so I sorted it :
public static <K extends Comparable,V extends Comparable> Map<K,V> sortByValues(Map<K,V> map){
List<Map.Entry<K,V>> entries = new LinkedList<Map.Entry<K,V>>(map.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<K,V>>() {
#Override
public int compare(Entry<K, V> o1, Entry<K, V> o2) {
return o2.getValue().compareTo(o1.getValue());
}
});
Map<K,V> sortedMap = new LinkedHashMap<K,V>();
for(Map.Entry<K,V> entry: entries){
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
but HOW DO I print the first 40?.... if you use the code above and say:
System.out.println(sortByValues(doubleCount));
you get a sorted hashMap by value.
but HOW DO I PRINT ONLY THE FIRST 40????
Try:
int i = 0;
for(Map.Entry<K,V> entry: sortByValues(doubleCount)){
System.out.println(entry.getKey() + ": " + entry.getValue());
if (++i == 40) break;
}
?
Can you not use
"public Collection<V> values()"
function of HashMap to get all values then use
for(int i=0; i<40; i++){System.out.println(valuelist.get(i))}

Categories