I want to sort the map. I have string as key and integer as value.
Example:
key value
"1,3" 40
"1,5" 20
"2,5" 10
"2,10" 30
Output:
"2,5" 10
"1,5" 20
"2,10" 30
"1,3" 40
I tried the below code but it is not working. Can you please help me out.
treemap = treemap = new TreeMap<String, Integer>();
while((line = br.readLine()) !=null )
{
int sum=0;
sum = //something
String keys = xCordinate + "," + yCordinate; //getting it
treemap.put(keys, sum);
}
testMap(treemap );
}
public static void testMap(Map <String,Integer> map)
{
for(Integer value1 : map.values())
{
String keys = map.get(value1).toString(); //error in this line
System.out.println(keys + " " + value1);
}
}
Here, I get the perfect values in treemap..When I debug and see, the key value and count are perfect, but when i go in for loop, theere comes an error in second line.
StackTrace
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at java.lang.Integer.compareTo(Unknown Source)
at java.util.TreeMap.getEntry(Unknown Source)
at java.util.TreeMap.get(Unknown Source)
at TestJavaServer.testMap(TestJavaServer.java:75)
at TestJavaServer.readFromFile(TestJavaServer.java:68)
at TestJavaServer.main(TestJavaServer.java:22)
Asuming Java ,you could sort hashmap just like this :
public LinkedHashMap sortHashMapByValuesD(HashMap passedMap) {
List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
LinkedHashMap sortedMap = new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
String comp1 = passedMap.get(key).toString();
String comp2 = val.toString();
if (comp1.equals(comp2)){
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((String)key, (Double)val);
break;
}
}
}
return sortedMap;
}
Just a kick-off example , This way is more useful as it sorts the HashMap and keeps the duplicate values as well.
When you call map.get(something), that something must be of the same type as the map's key (String in your case), but you are passing in an Integer.
The code
public static void testMap(Map <String,Integer> map)
says that your map has keys of the type String, whereas here
String keys = map.get(value1).toString(); //error in this line
--
value1 is an integer, hence the exception.
Related
Can I pass a key of a value into variable in hashmap?
For example I have a key 987456321 for value "A". How to pass the key in a variable so that I can further subdivide the key and print it as 987-654-321,
by taking 987 as first,
654 as middle,
321 as last
So that I can print
first+ "-" + middle+ "-" + last as 987-654-321
by using toString() method.
I am new to Java, So help me Please
public static void main(String[] args)
{
HashMap<Long, String> hashMap = new HashMap<>();
hashMap.put(987456321L, "A");
hashMap.put(321654998L, "B");
hashMap.put(874563210L, "C");
hashMap.put(987453216L, "B");
hashMap.put(321650123L, "C");
hashMap.put(874568745L, "C");
System.out.println("Size of Map:"+hashMap.size());
System.out.println("Enter no: ");
userInput = new Scanner(System.in);
no = userInput.nextLong();
String name = hashMap.get(no);
System.out.println(name);
for (Map.Entry<Long, String> entry : hashMap.entrySet())
{
String key = entry.getKey().toString();
String value = entry.getValue();
System.out.println("name " + value + "- Number " + key);
}
}
You can iterate over all key-value-pairs of your map like this:
for (final Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
// do whatever you need to do with key
}
If you're interested in a key for a certain value only - makes not much sense as the same value might be stored in a map with different keys - you will need to check for the value in the above loop until you found the key-value-pair of interest. E.g.:
if (Objects.equals(value, "A")) {
// do something with the key for value "A"
}
1. Solution for specific value:
This method returns keys for your value
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
Set<T> keys = new HashSet<T>();
for (Entry<T, E> entry : map.entrySet()) {
if (Objects.equals(value, entry.getValue())) {
keys.add(entry.getKey());
}
}
return keys;
}
Now all you have to do is to iterate through returned set and do what you want with variable which contains your key
for (Long key : set) {
String s = String.valueOf(key);
}
I have this structure:
private HashMap<Integer,HashMap<Object,Integer>> commandList= new HashMap<>();
populated this way:
{1={1=2, 2=3, 3=4, -999=-999, -998=-998}}
from this code:
if ((msgTypeTemp=commandList.get(this.msgType).get(msgContent))==null) {
Object s= "1";
System.out.println("Class of s: "+s.getClass().getSimpleName()+"\nClass of msgContent: "+msgContent.getClass().getSimpleName());
System.out.println("msgMap:\n"+msgMap);
System.out.println("commandList:\n"+commandList);
System.out.println(s.hashCode());
System.out.println(msgContent.hashCode());
System.out.println(commandList.get(this.msgType).get(s));
this.msgType=JSockOS_UndefinedMsg.MSG_CODE;
specialMsg=true;
} else {
this.msgType=msgTypeTemp;
if (specialMsgType(this.msgType)){
specialMsg=true;
}
}
My HashMap is generic type <String,Integer>
However, whenever I call the get method on msgContent, it comes out that instead of the hashcode of "1", it was a hashcode which until that moment was set to 0, and which then changed after the get method call.
This happens only for calls that use "msgContent" parameter...
If I use this: System.out.println(commandList.get(this.msgType).get(s));
It returns "2" as expected...
Look also this image, it may help.
msgContent gets changed before the above code in this way:
it was first: 2.1.
then it gets: 1.
remaining a string.
msgContent=msgContent.toString().split(Pattern.quote("."))[1];
do(msgContent); // a methods which implements the code showed before.
//msgContent is a parameter, --> public void do(Object msgContent)
[EDIT]:
PROBLEM FOUND: msgContent is 495 chars... will fix its changes and update!
Even though String is immutable, the value of hashCode is computed lazily for performance reasons, as shown here:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
As far as your actual problem is, are you entirely certain that your keys are String? The type you've provided there is <Object, Integer>, not <String, Integer>.
My test case works fine as shown here (this prints elseSide):
public static void main(String... args) {
HashMap<Integer, HashMap<Object, Integer>> map = new HashMap<>();
HashMap<Object, Integer> innerMap = new HashMap<>();
innerMap.put("1", 2);
innerMap.put("2", 3);
innerMap.put("-999",-999);
innerMap.put("-998",-998);
map.put(1, innerMap);
int msgType = 1;
String msgContent = "2.1";
msgContent = msgContent.toString().split(Pattern.quote("."))[1];
System.out.println(map);
if(map.get(msgType).get(msgContent) == null) {
System.out.println("ifSide");
} else {
System.out.println("elseSide");
}
}
I think you should try adding the following debugging statements:
HashMap<Object, Integer> innerMap = commandList.get(this.msgType);
for(Map.Entry<Object, Integer> entry : innerMap.entrySet()) {
System.out.println("KeyClass: " + entry.getKey().getClass() +
"\tKeyValue:" + entry.getKey());
// This will make sure the string doesn't have any unprintable characters
if(entry.getKey() instanceof String) {
String key = (String) entry.getKey();
System.out.println("Key Length: " + key.getLength());
}
}
I don't think your key in your inner map is actually a String, or perhaps the String somehow has unprintable characters. A hash of 630719471 is much too high for a one character String. It's also possible that msgContent has unprintable characters as well.
I have an homework to do, so I have finished the script but the problem is with the values.
The main code is (I cannot change it due to homework) :
List<String> result = cw.getResult();
for (String wordRes : result) {
System.out.println(wordRes);
}
It have to return:
abc 2
def 2
ghi 1
I have no idea how to handle that.
Now only shows:
abc
def
ghi
I have no idea how to change this method getResult to return with the value of the hashmap as well without changing the first main code.
public List<String> getResult() {
List<String> keyList = new ArrayList<String>(list.keySet());
return keyList;
}
The hashmap is: {abc=2, def=2, ghi=1}
And list: Map<String, Integer> list = new HashMap<String, Integer>();
Please help me if you know any resolution.
I think that now that you have learned about keySet and valueSet, your next task is to learn about entrySet. That's a collection of Map.Entry<K,V> items, which are in turn composed of the key and the value.
That's precisely what you need to complete your task - simply iterate over the entrySet of your Map while adding a concatenation of the value and the key to your result list:
result.add(entry.getKey() + " " + entry.getValue());
Note that if you use a regular HashMap, the items in the result would not be arranged in any particular order.
You need to change this line:
List<String> keyList = new ArrayList<String>(list.keySet());
to:
//first create the new List
List<String> keyList = new List<String>();
//iterate through the map and insert the key + ' ' + value as text
foreach(string item in list.keySet())
{
keyList.add(item+' '+list[item]);
}
return keyList;
I haven't written java in a while so compiler errors might appear, but the idea should work
Well simplest way make an ArrayList and add as #dasblinkenlight said...
Iterator<?> it = list.entrySet().iterator();
while (it.hasNext()) {
#SuppressWarnings("rawtypes")
Map.Entry maps = (Map.Entry) it.next();
lista.add(maps.getKey() + " " + maps.getValue());
}
}
public List<String> getResult() {
List<String> temp = lista;
return temp;
}
If you want to iterate over map entries in order of keys, use an ordered map:
Map<String, Integer> map = new TreeMap<String, Integer>();
Then add your entries, and to print:
for (Map.Entry<String, Ibteger> entry : map.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
I want to retrieve k,v-pairs from a HashMap.
The entrys are like this:
a = 3,4
b = 5,6
and so on. I need combinations of these values.
a=3, b=5
a=3, b=6
a=4, b=5
a=4, b=6
I don't know how many keys and how many entrys the values have. With entrySet I can get the values but not combinations. It looks like recursion but how?
Here's my code:
HashMap<String, String[]> map = new HashMap<String, String[]>();
BufferedReader file = new BufferedReader(new FileReader("test.txt"));
String str;
while ((str = file.readLine()) != null) {
// ... logic
map.put(key, value);
}
System.out.println("number of keys: " + map.size());
for (Map.Entry<String, String[]> entry : map.entrySet()) {
for (String value : entry.getValue()) {
System.out.println(entry.getKey() + ": " + value);
}
}
file.close();
You can try the following code:
public void mapPermute(Map<String, String[]> map, String currentPermutation) {
String key = map.keySet().iterator().next(); // get the topmost key
// base case
if (map.size() == 1) {
for (String value : map.get(key)) {
System.out.println(currentPermutation + key + "=" + value);
}
} else {
// recursive case
Map<String, String[]> subMap = new HashMap<String, String[]>(map);
for (String value : subMap.remove(key)) {
mapPermute(subMap, currentPermutation + key + "=" + value + ", ");
}
}
}
No guarantees on memory efficiency or speed. If you want to preserve the order of the keys in the map, you will have to pass in a TreeMap and change the code to use a TreeMap under the recursive case.
As the base case suggests, I'm assuming you have at least one entry in your map.
You can obtain a Cartesian product of map key-value combinations using a map and reduce approach.
Try it online!
Map<String, String[]> map = Map.of(
"a", new String[]{"3", "4"},
"b", new String[]{"5", "6"});
List<Map<String, String>> comb = map.entrySet().stream()
// Stream<List<Map<String,String>>>
.map(e -> Arrays.stream(e.getValue())
.map(v -> Map.of(e.getKey(), v))
.collect(Collectors.toList()))
// summation of pairs of list into a single list
.reduce((list1, list2) -> list1.stream()
// combinations of inner maps
.flatMap(map1 -> list2.stream()
// concatenate into a single map
.map(map2 -> {
Map<String, String> m = new HashMap<>();
m.putAll(map1);
m.putAll(map2);
return m;
}))
// list of combinations
.collect(Collectors.toList()))
// otherwise, an empty list
.orElse(Collections.emptyList());
// output, order may vary
comb.forEach(System.out::println);
Output, order may vary:
{a=3, b=5}
{a=3, b=6}
{a=4, b=5}
{a=4, b=6}
See also: Cartesian product of map values
It looks to me like you really want a MultiMap. In particular, ArrayListMultimap allows duplicate entries:
ArrayListMultimap<String, String> map = ArrayListMultimap.create();
for each line in file:
parse key k
for each value in line:
parse value v
map.put(k, v);
for (Map.Entry<String, String> entry : map.entries()) {
String key = entry.getKey();
String value = entry.getValue();
}
If you want a cartesian product of maps, you could compute that directly using recursion, or you could iterate over the maps: create a list of iterators and iterate odometer-style; when iterator N reaches its end, advance iterator N+1 and reset iterators 1..N.
Just poked around and found this SO question.
So I'd recommend you use guava's Sets.cartesianProduct for the cartesian product. Here's my poking around code, which you could adapt to your input logic:
String key1 = "a";
Set<Integer> values1 = Sets.newLinkedHashSet(Arrays.asList(1, 2, 3, 4));
String key2 = "b";
Set<Integer> values2 = Sets.newLinkedHashSet(Arrays.asList(5, 6, 7));
String key3 = "c";
Set<Integer> values3 = Sets.newLinkedHashSet(Arrays.asList(8, 9));
List<String> keys = Arrays.asList(key1, key2, key3);
Set<List<Integer>> product = Sets.cartesianProduct(values1, values2, values3);
for (List<Integer> values : product) {
for (int i = 0; i < keys.size(); ++i) {
String key = keys.get(i);
int value = values.get(i);
System.out.print(key + "=" + value + "; ");
}
System.out.println();
}
This question already has answers here:
How do I efficiently iterate over each entry in a Java Map?
(46 answers)
Closed 7 years ago.
I have this field:
HashMap<String, HashMap> selects = new HashMap<String, HashMap>();
For each Hash<String, HashMap> I need to create a ComboBox, whose items are the value (which happens to be a HashMap itself) of HashMap <String, **HashMap**>.
By way of (non-functioning) demonstration:
for (int i=0; i < selects.size(); i++) {
HashMap h = selects[i].getValue();
ComboBox cb = new ComboBox();
for (int y=0; y < h.size(); i++) {
cb.items.add(h[y].getValue);
}
}
I know I'm a bit late for that one, but I'll share what I did too, in case it helps someone else :
HashMap<String, HashMap> selects = new HashMap<String, HashMap>();
for(Map.Entry<String, HashMap> entry : selects.entrySet()) {
String key = entry.getKey();
HashMap value = entry.getValue();
// do what you have to do here
// In your case, another loop.
}
Lambda Expression Java 8
In Java 1.8 (Java 8) this has become lot easier by using forEach method from Aggregate operations(Stream operations) that looks similar to iterators from Iterable Interface.
Just copy paste below statement to your code and rename the HashMap variable from hm to your HashMap variable to print out key-value pair.
HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
/*
* Logic to put the Key,Value pair in your HashMap hm
*/
// Print the key value pair in one line.
hm.forEach((k,v) -> System.out.println("key: "+k+" value:"+v));
Here is an example where a Lambda Expression is used:
HashMap<Integer,Integer> hm = new HashMap<Integer, Integer>();
Random rand = new Random(47);
int i=0;
while(i<5){
i++;
int key = rand.nextInt(20);
int value = rand.nextInt(50);
System.out.println("Inserting key: "+key+" Value: "+value);
Integer imap =hm.put(key,value);
if( imap == null){
System.out.println("Inserted");
}
else{
System.out.println("Replaced with "+imap);
}
}
hm.forEach((k,v) -> System.out.println("key: "+k+" value:"+v));
Output:
Inserting key: 18 Value: 5
Inserted
Inserting key: 13 Value: 11
Inserted
Inserting key: 1 Value: 29
Inserted
Inserting key: 8 Value: 0
Inserted
Inserting key: 2 Value: 7
Inserted
key: 1 value:29
key: 18 value:5
key: 2 value:7
key: 8 value:0
key: 13 value:11
Also one can use Spliterator for the same.
Spliterator sit = hm.entrySet().spliterator();
UPDATE
Including documentation links to Oracle Docs.
For more on Lambda go to this link and must read Aggregate Operations and for Spliterator go to this link.
Map.values():
HashMap<String, HashMap<SomeInnerKeyType, String>> selects =
new HashMap<String, HashMap<SomeInnerKeyType, String>>();
...
for(HashMap<SomeInnerKeyType, String> h : selects.values())
{
ComboBox cb = new ComboBox();
for(String s : h.values())
{
cb.items.add(s);
}
}
Streams Java 8
Along with forEach method that accepts a lambda expression we have also got stream APIs, in Java 8.
Iterate over entries (Using forEach and Streams):
sample.forEach((k,v) -> System.out.println(k + "=" + v));
sample.entrySet().stream().forEachOrdered((entry) -> {
Object currentKey = entry.getKey();
Object currentValue = entry.getValue();
System.out.println(currentKey + "=" + currentValue);
});
sample.entrySet().parallelStream().forEach((entry) -> {
Object currentKey = entry.getKey();
Object currentValue = entry.getValue();
System.out.println(currentKey + "=" + currentValue);
});
The advantage with streams is they can be parallelized easily and can be useful when we have multiple CPUs at disposal. We simply need to use parallelStream() in place of stream() above. With parallel streams it makes more sense to use forEach as forEachOrdered would make no difference in performance. If we want to iterate over keys we can use sample.keySet() and for values sample.values().
Why forEachOrdered and not forEach with streams ?
Streams also provide forEach method but the behaviour of forEach is explicitly nondeterministic where as the forEachOrdered performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. So forEach does not guarantee that the order would be kept. Also check this for more.
You can iterate over a HashMap (and many other collections) using an iterator, e.g.:
HashMap<T,U> map = new HashMap<T,U>();
...
Iterator it = map.values().iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
I generally do the same as cx42net, but I don't explicitly create an Entry.
HashMap<String, HashMap> selects = new HashMap<String, HashMap>();
for (String key : selects.keySet())
{
HashMap<innerKey, String> boxHolder = selects.get(key);
ComboBox cb = new ComboBox();
for (InnerKey innerKey : boxHolder.keySet())
{
cb.items.add(boxHolder.get(innerKey));
}
}
This just seems the most intuitive to me, I think I'm prejudiced against iterating over the values of a map.
Use entrySet,
/**
*Output:
D: 99.22
A: 3434.34
C: 1378.0
B: 123.22
E: -19.08
B's new balance: 1123.22
*/
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MainClass {
public static void main(String args[]) {
HashMap<String, Double> hm = new HashMap<String, Double>();
hm.put("A", new Double(3434.34));
hm.put("B", new Double(123.22));
hm.put("C", new Double(1378.00));
hm.put("D", new Double(99.22));
hm.put("E", new Double(-19.08));
Set<Map.Entry<String, Double>> set = hm.entrySet();
for (Map.Entry<String, Double> me : set) {
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
System.out.println();
double balance = hm.get("B");
hm.put("B", balance + 1000);
System.out.println("B's new balance: " + hm.get("B"));
}
}
see complete example here:
http://www.java2s.com/Code/JavaAPI/java.util/HashMapentrySet.htm