adding to Maps in Java - java

Hi i am trying to add countries to a map see below code. I am able to input the countries but my out is not what i expected. The Set prints out 4 times where i want each country counting form 1-4 not each Set. can you help?
/**
* MY CODE SO FAR = pleae can you help
*/
import java.util.*;
class EuroGroupStages {
public static void main(String args[]) {
Map<Integer, Set<String>> groupA;
Map<Integer, Set<String>> groupB;
Map<Integer, Set<String>> groupC;
Map<Integer, Set<String>> groupD;
//public EuroGroupStages()
// {
groupA = new TreeMap<>();
groupB = new TreeMap<>();
groupC = new TreeMap<>();
groupD = new TreeMap<>();
// }
//public void addCountries()
// {
Scanner keyboard = new Scanner(System.in);
Set<String> country = new HashSet<>();
String aCountry;
for(int i = 1; i < 5; i++)
{
System.out.print("Please enter a country");
aCountry = keyboard.next();
country.add(aCountry);
groupA.put(i, country);
}
System.out.println(groupA);
keyboard.close();
// }
}
}
{1=[England, Scotland, Czech, Croatia], 2=[England, Scotland, Czech, Croatia], 3=[England, Scotland, Czech, Croatia], 4=[England, Scotland, Czech, Croatia]}

Instead of System.out.println(groupA);
try to write:
for(int i = 1; i < 5; i++)
{
System.out.println(groupA.get(i));
}
for getting the value of each key in groupA.
Edit:
Here are some examples for getting the combinations of key+value:
(https://www.techiedelight.com/iterate-map-using-keyset-java/)
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Stream;
public class Main
{
// Program to iterate map using `keySet()` in Java
public static void main(String[] args)
{
Map<Integer, String> map = new HashMap<>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
map.put(4, "Four");
// 1. Using an iterator
Iterator<Integer> itr = map.keySet().iterator();
while (itr.hasNext())
{
Integer key = itr.next();
String value = map.get(key);
System.out.println(key + "=" + value);
}
// 2. For-each loop
for (Integer key: map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
// 3. Java 8 - Iterator.forEachRemaining()
map.keySet()
.iterator()
.forEachRemaining(key -> System.out.println(key + "=" + map.get(key)));
// 4. Java 8 - Stream.forEach()
map.keySet().stream()
.forEach(key -> System.out.println(key + "=" + map.get(key)));
// 5. Java 8 - Stream.of() + toArray() + forEach()
Stream.of(map.keySet().toArray())
.forEach(key -> System.out.println(key + "=" + map.get(key)));
}
}
Code is compileable in java-online compiler:
(https://www.tutorialspoint.com/compile_java_online.php)
One of these approaches is certainly applicable to your code.

You're putting each country in a set and then adding the whole set each time. What I think you want to do is to put the countries in individual sets and add those to the map (more information would be helpful). To do this, a new Set must be created in each iteration of the loop to hold the next country.
// first you can delare you maps like this.
Map<Integer, Set<String>> groupA= new TreeMap<>();
Scanner keyboard = new Scanner(System.in);
for(int i = 1; i < 5; i++) {
System.out.print("Please enter a country");
Set<String> country = new HashSet<>();
country.add(keyboard.next());
groupA.put(i, country);
}
groupA.entrySet().forEach(System.out::println);
Prints something like
1=[USA]
2=[Canada]
3=[Norway]
4=[England]
And do not close the Scanner when taking input from the keyboard.

Related

Why it returns null, but not String in HashMap? java

How could I get values from Map? I study Collections and wanna leave that order <String, Integer>.
I tried before <Integer, String> and in loop I put res.append(map.get(num)); — that's help me. But have no clue how to do it in reverse order.
Also I red https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html#get-java.lang.Object-, but I know exactly that I have a key..
import java.util.LinkedHashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
int x = 555;
String result = romanianConverter(x);
System.out.println(result);
}
public static String romanianConverter(int value) {
Map<String, Integer> map = new LinkedHashMap<>();
// map.put(1000, "M");
// map.put(900,"CM");
// map.put(500,"D");
// map.put(400,"CD");
// map.put(100,"C" );
// map.put(90,"XC" );
// map.put(50,"L" );
// map.put(40,"XL");
// map.put(10,"X" );
// map.put(9,"IX" );
// map.put(5,"V" );
// map.put(4,"IV" );
// map.put(1,"I" );
map.put("M", 1000);
map.put("CM", 900);
map.put("D", 500);
map.put("CD", 400);
map.put("C", 100);
map.put("XC", 90);
map.put("L", 50);
map.put("XL", 40);
map.put("X", 10);
map.put("IX", 9);
map.put("V", 5);
map.put("IV", 4);
map.put("I", 1);
StringBuilder stringBuilder = new StringBuilder("Result = ");
for (int number2 : map.values()) {
while (number2 <= value) {
stringBuilder.append(map.keySet().add(number2));
value -= number2;
}
}
return stringBuilder.toString();
}
}
Traversing a HashMap is pretty straightforward. First of all you have to understand that the first Class in the <> diamond brackets is the KEY and the second is the VALUE.
So if I create a new HashMap<Integer, String> the elements will be of the following form
1 -> "str",
2 -> "str2"
....
To traverse this HashMap And we want only the keys this is the way to do it:
Map<String, Object> map = ...;
for (Integer key : map.keySet()) {
// ...
}
If we want only the values:
for (String value : map.values()) {
// ...
}
If we want them both:
for (Map.Entry<Integer, String> entry : map.entrySet()) {
Integer key = entry.getKey();
String value = entry.getValue();
// ...
}
Still I am sure you are trying to conver integers in Roman Numerals.
This already has a solution here.
In current implementation you need to iterate the map entries returned by Map::entrySet method to use the key as soon as the value is found:
// ...
for (Map.Entry<String, Integer> me: map.entrySet()) {
int number2 = me.getValue();
while (number2 <= value) {
stringBuilder.append(me.getKey());
value -= number2;
}
}
// ...
Or, if the reverse map is implemented Map<Integer, String> map a keySet should be iterated:
for (Integer number2: map.keySet()) {
while (number2 <= value) {
stringBuilder.append(map.get(number2));
value -= number2;
}
}

Using Hashmaps to compare keys and values and add together values based on similar keys

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));
}

How to get input from user for Hashmap using Scanner

How to get input from user for Hashmap using scanner and print the respective hashmap?
import java.util.HashMap;
import java.util.Scanner;
public class Map {
public static void main(String[] args) {
HashMap<Integer, Integer> hmap = new HashMap<>();
Scanner in = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
Integer a = in.nextInt();
Integer b = in.nextInt();
hmap.put(a, b);
System.out.println(hmap.put(a, b));
}
}
}
I am not getting the desired output. I want to print what is inserted in hmap.
Change your System.out.println statement to,
System.out.println(hmap.get(a));
This is another way to put data into a HashMap at runtime:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
class MapDemo {
public static void main(String[] args) {
HashMap<Integer, String> hmap = new HashMap<>();
Scanner in = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
Integer a = in.nextInt();
String b = in.next();
hmap.put(a, b);
}
for (Map.Entry<Integer, String> m : hmap.entrySet()) {
System.out.println(m.getKey() + " " + m.getValue());
}
}
}
Javadoc for the HashMap util can be found here.
To add a key/value pair to a HashMap you use hashmap.put(x, y).
Using hashmap.get(x) at a later time will return y.
Edit: It looks like from other comments you are trying to have it print out both the key and the value. In the case that you are trying to print out all keys and values something like this may work.
hashMap.forEach((e, k) -> {
System.out.println("E: " + e + " K: " + k);
})
If this is not your intended purpose I would strongly recommend reading over the method summary section of the javadocs.
What do you expect this to do? It is wrong, why would you print hmap.put(a,b)
System.out.println(hmap.put(a,b));
Just take it out of the for loop and print it separately
for (Map.Entry<Integer, Integer> pair: hmap.entrySet()) {
System.out.println(pair.getKey() + "->" + pair.getValue());
}
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
class Call {
public static void main(String[] as) {
getData();
}
public static void getData() {
Map<Integer, String> hashmap = new HashMap<>();
Scanner sc = new Scanner(System.in);
System.out.print("Shashank Pathak\nEnter number of character: ");
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < a.length; i++) {
Integer b = sc.nextInt();
String c = sc.nextLine();
hashmap.put(b, c);
}
for (Map.Entry<Integer, String> mp : hashmap.entrySet()) {
System.out.println("\n" + mp.getKey() + " " + mp.getValue());
}
}
}
I find this, And it is exactly the same as I want.
System.out.println("How many producs you want");
int listOfItem = sc.nextInt();
System.out.println("Type the product name and quantity you want to purchace and get the bill");
HashMap<Integer, String> products = new HashMap<>();
while(listOfItem-- >0){
products.put(sc.nextInt(),sc.nextLine());
}
System.out.println(products);
Output of above program
import java.util.*;
class hash1 {
void dic(){
HashMap<Integer,Integer> hmap = new HashMap<Integer,Integer>();
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
hmap.put(a,b);
System.out.println(hmap);
}
}
public class answer {
public static void main(String[] args) {
hash1 obj = new hash1();
for(int z = 0;z < 3;z++){
obj.dic();
}
}
}

Collections which increase number of occurrences instead of adding duplicate

Does exist any collection which stores only unique strings, but count how many times this string was added?
So every time, when I try add the same string/item again, number of items remain the same but numbers of occurrence of given item will increase?
You can use a HashMap and wrap some code around it:
public class CounterMap<K> {
private final Map<K, Integer> internalMap = new HashMap<K, Integer>();
public void increment(K key) {
initKeyIfNew(key);
Integer oldValue = internalMap.get(key);
Integer newValue = oldValue + 1;
internalMap.put(key, newValue);
}
public int getCount(K key) {
initKeyIfNew(key);
return internalMap.get(key);
}
private void initKeyIfNew(K key) {
if (internalMap.get(key) == null) {
internalMap.put(key, 0);
}
}
}
Then you can use it like this:
CounterMap<String> myCounterMap = new CounterMap<String>();
myCounterMap.increment("hello");
...
As far as I know, there is not such build in collections, but you can simply achieve that by using Map collection:
Map<String, Integer> map = new HashMap<>();
String sample = "foo";
if (map.containsKey(sample))
map.put(sample, map.get(sample) + 1);
You can also use solution from external library, for example Multiset from Google Guava:
Multiset<String> multiset = HashMultiset.create();
String test = "foo";
multiset.add(test);
multiset.add(test);
multiset.add(test);
System.out.println(multiset.count(test));
with output:
3
Hope it helps.
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class UniqueStringCount {
public static void main(String[] args) {
boolean takeUserInput = true;
HashMap<String, Integer> uniqueStringMap = new HashMap<>();
int counter = 0;
System.out.println("Welcome. To close the program type exit.");
System.out.println();
do {
Scanner scan = new Scanner(System.in);
System.out.println("Enter the unique string");
String userInput = scan.next();
if(userInput.equalsIgnoreCase("exit")) {
takeUserInput = false;
scan.close();
}
System.out.println();
if(!userInput.equalsIgnoreCase("exit")) {
if(uniqueStringMap.containsKey(userInput)) {
counter = uniqueStringMap.get(userInput);
uniqueStringMap.put(userInput, ++counter);
continue;
}
counter = 0;
uniqueStringMap.put(userInput, ++counter);
}
} while(takeUserInput);
if(!uniqueStringMap.isEmpty()) {
for(Map.Entry<String, Integer> entry : uniqueStringMap.entrySet()) {
System.out.println("String " + entry.getKey() + " was added " + entry.getValue() + " times.");
System.out.println();
}
System.out.println("Bye bye.");
}
}
}
With Java 8:
Map<String, Integer> map = new HashMap<>();
When adding a string, do:
map.merge(s, 1, Integer::sum);
What this does is add the string s and set the value to 1 if it wasn't there yet. If it was there already, then it takes the current value and the new value you're adding (1 again) and sums them, and puts that back into the map.

Need a Fresh pair of Eyes to Work Out the Logic Behind Comparing Values in a Map of Maps

Problem
Data is in the format:
Map<String, Map<String, Integer>>
Which looks something like this:
{"MilkyWay": {"FirstStar" : 3, "SecondStar" : 9 .... }, "Andromeda": {"FirstStar" : 10, "SecondStar" : 9 .... } }
I want to compare the Star values in a quick loop, so I'd like to compare the integer value of FirstStar in MilkyWay and Andromeda and have it return true or falseif the values are the same or not. Since this Map of Maps is huge.
My Attempt
I'd like to do it something like:
//GalaxyMap<String, <Map<String, Integer>>
for (Map<String, Integer> _starMap : GalaxyMap.values())
{
for (String _starKey : _starMap.keySet()){
//Can't quite think of the correct logic... and I'm tired...
}
}
I'd like to keep it as short as possible... I've been staring at this for a while and I'm going in circles with it.
EDIT
Outer keys differ, Inner keys are the same
Also since this is a response from a server, I don't know the size it's going to be
Why does this need to be a map. If you're always using "FirstStar", "SecondStar" etc, as your keys, then why not make it a list instead..
Map<String, List<Integer>>
Then you can do something like:
public boolean compareGalaxyStar(String galaxyName, String otherGalaxyName, int star) {
List<Integer> galaxyStars = galaxyMap.get(galaxyName);
List<Integer> otherGalaxyStars = galaxyMap.get(otherGalaxyName);
return galaxyStars.get(star) == otherGalaxyStars.get(star);
}
NOTE: You need to do some validation to make sure the input is correct.
To implement this for all stars, it is not much different.
if(galaxyStars.size() == otherGalaxyStars.size()) {
for(int x = 0; x < galaxyStars.size(); x++) {
// Perform your comparisons.
if(galaxyStars.get(x) != otherGalaxyStars.get(x)) {
// Uh oh, unequal.
return false;
}
}
}
If the structure of the inner maps also could differ, you should do something like that:
static boolean allStarValuesEqual(Map<String, Map<String, Integer>> galaxies) {
Map<String, Integer> refStars = null;
for (Map<String, Integer> galaxy : galaxies.values()) {
if (refStars == null) {
refStars = galaxy;
} else {
for (Entry<String, Integer> currentStar : galaxy.entrySet()) {
if (!currentStar.getValue().equals(refStars.get(currentStar.getKey()))) {
return false;
}
}
}
}
return true;
}
Please check below program along with output:
package com.test;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class CompareMapValues {
private final static String FS = "FirstStar";
private final static String SS = "SecondStar";
private final static String MW = "MilkyWay";
private final static String A = "Andromeda";
public static void main(String[] args) {
Map> map = new HashMap>();
Map innerMap1 = new HashMap();
innerMap1.put(FS, 3);
innerMap1.put(SS, 9);
Map innerMap2 = new HashMap();
innerMap2.put(FS, 10);
innerMap2.put(SS, 9);
map.put(MW, innerMap1);
map.put(A, innerMap2);
Set set = map.keySet();
for(String s: set) {
Map outerMap = map.get(s);
Set set2 = map.keySet();
for(String s2: set2) {
Map innerMap = map.get(s2);
if(!s2.equals(s)) {
Set set3 = outerMap.keySet();
for(String s3: set3) {
int i1 = outerMap.get(s3);
Set set4 = innerMap.keySet();
for(String s4: set4) {
int i2 = innerMap.get(s3);
if(s3.equals(s4) && i1==i2) {
System.out.println("For parent " + s + " for " + s3 + " value is " + i1);
}
}
}
}
}
}
}
}
//Output:
//For parent Andromeda for SecondStar value is 9
//For parent MilkyWay for SecondStar value is 9
Hope this helps.

Categories

Resources