I am not able to get the value of the string i have entered according to my mapped values??
I want the value which i want to get as 8118198920
import java.util.*;
class maptable1 {
public static void main(String args[]) {
HashMap<String, Integer> hm =
new HashMap<String, Integer>();
hm.put("A", Integer.valueOf(1));
hm.put("B", Integer.valueOf(2));
hm.put("C", Integer.valueOf(3));
hm.put("D", Integer.valueOf(4));
hm.put("E", Integer.valueOf(5));
hm.put("F", Integer.valueOf(6));
hm.put("G", Integer.valueOf(7));
hm.put("H", Integer.valueOf(8));
hm.put("I", Integer.valueOf(9));
hm.put("J", Integer.valueOf(10));
hm.put("K", Integer.valueOf(11));
hm.put("L", Integer.valueOf(12));
hm.put("M", Integer.valueOf(13));
hm.put("N", Integer.valueOf(14));
hm.put("O", Integer.valueOf(15));
hm.put("P", Integer.valueOf(16));
hm.put("Q", Integer.valueOf(17));
hm.put("R", Integer.valueOf(18));
hm.put("S", Integer.valueOf(19));
hm.put("T", Integer.valueOf(20));
hm.put("U", Integer.valueOf(21));
hm.put("V", Integer.valueOf(22));
hm.put("W", Integer.valueOf(23));
hm.put("X", Integer.valueOf(24));
hm.put("Y", Integer.valueOf(25));
hm.put("Z", Integer.valueOf(26));
System.out.println("The Value is: " + hm.get("HARSHIT"));
}
}
Hash maps don't work like that.
To produce what you want, you need to call hm.get() with each character in the string, convert the integer you get to a string, and join all of these strings together.
One way to implement this is to use streams:
// "s" is a string variable containing "HARSHIT"
String result = s.chars().mapToObj(x -> Character.toString((char)x))
.map(x -> Integer.toString(hm.get(x)))
.collect(Collectors.joining());
Also note that you don't need Integer.valueOf. You can just use the integer itself.
Related
I have a string in java
String s="a=one b=two c=three d=four e=five"
and i want to print the value of c i.e; three.
I took StringTokenizer and i got.
a=one
b=two
c=three
d=four
e=five
and i want to print the value of c i.e; three.
For a one line solution, you could use String#replaceAll:
String input = "a=one b=two c=three d=four e=five";
String cValue = input.replaceAll(".*\\bc=(.+?)\\b.*", "$1");
System.out.println("c: " + cValue);
This prints:
c: three
If you want to go the route of splitting to an array of key value pairs, then consider using streams:
String input = "a=one b=two c=three d=four e=five";
String cValue = Arrays.stream(input.split("\\s+"))
.filter(x -> "c".equals(x.split("=")[0]))
.map(x -> x.split("=")[1])
.collect(Collectors.toList())
.get(0);
In case you know that the letter values are unique, you can convert it to Map, using streams. I wrote a quick method in test package for you
#Test
public void test() {
String s="a=one b=two c=three d=four e=five";
Map<String, String> myMap = Arrays.stream(s.split(" ")).collect(
Collectors.toMap(
key -> key.split("=")[0],
value -> value.split("=")[1]
)
);
System.out.println(myMap.get("c"));
}
How does it work?
It takes your string, splits it first by spaces - as a result you end up with the List of Strings. Then you process it as a stream, use static factory method toMap from Collectors class and split key and value by "=", creating a map (first value as a key, second converted to value) based on this. Then you can get any key value pair You want
Iterate the returned object from StringTokenizer and use the split function to split with = character,
split() will return array, check the 0th index with any character you want (in this case 'c'), if equal, return the 1st index
while (st1.hasMoreTokens()) {
String s = st1.nextToken();
String a[] = s.split("=");
if(a[0) == "c") {
System.out.println(a[1]);
}
}
I have list that has alphanumeric elements. I want to find the maximum number of each elements individually.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Collect {
public static void main(String[] args) {
List<String> alphaNumericList = new ArrayList<String>();
alphaNumericList.add("Demo.23");
alphaNumericList.add("Demo.1000");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Test.01");
alphaNumericList.add("Test.02");
alphaNumericList.add("Test.100");
alphaNumericList.add("Test.99");
Collections.sort(alphaNumericList);
System.out.println("Output "+Arrays.asList(alphaNumericList));
}
I need filter only below values. For that I am sorting the list but it filters based on the string rather than int value. I want to achieve in an efficient way. Please suggest on this.
Demo.1000
Test.100
Output [[Demo.1000, Demo.12, Demo.12, Demo.23, Test.01, Test.02, Test.100, Test.99]]
You can either create a special AlphaNumericList type, wrapping the array list or whatever collection(s) you want to use internally, giving it a nice public interface to work with, or for the simplest case if you want to stick to the ArrayList<String>, just use a Comparator for sort(..):
package de.scrum_master.stackoverflow.q60482676;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static java.lang.Integer.parseInt;
public class Collect {
public static void main(String[] args) {
List<String> alphaNumericList = Arrays.asList(
"Demo.23", "Demo.1000", "Demo.12", "Demo.12",
"Test.01", "Test.02", "Test.100", "Test.99"
);
Collections.sort(
alphaNumericList,
(o1, o2) ->
((Integer) parseInt(o1.split("[.]")[1])).compareTo(parseInt(o2.split("[.]")[1]))
);
System.out.println("Output " + alphaNumericList);
}
}
This will yield the following console log:
Output [Test.01, Test.02, Demo.12, Demo.12, Demo.23, Test.99, Test.100, Demo.1000]
Please let me know if you don't understand lambda syntax. You can also use an anonymous class instead like in pre-8 versions of Java.
Update 1: If you want to refactor the one-line lambda for better readability, maybe you prefer this:
Collections.sort(
alphaNumericList,
(text1, text2) -> {
Integer number1 = parseInt(text1.split("[.]")[1]);
int number2 = parseInt(text2.split("[.]")[1]);
return number1.compareTo(number2);
}
);
Update 2: If more than one dot "." character can occur in your strings, you need to get the numeric substring in a different way via regex match, still not complicated:
Collections.sort(
alphaNumericList,
(text1, text2) -> {
Integer number1 = parseInt(text1.replaceFirst(".*[.]", ""));
int number2 = parseInt(text2.replaceFirst(".*[.]", ""));
return number1.compareTo(number2);
}
);
Update 3: I just noticed that for some weird reason you put the sorted list into another list via Arrays.asList(alphaNumericList) when printing. I have replaced that by just alphaNumericList in the code above and also updated the console log. Before the output was like [[foo, bar, zot]], i.e. a nested list with one element.
Check below answer:
public static void main(String[] args) {
List<String> alphaNumericList = new ArrayList<String>();
alphaNumericList.add("Demo.23");
alphaNumericList.add("Demo.1000");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Demo.12");
alphaNumericList.add("Test.01");
alphaNumericList.add("Test.02");
alphaNumericList.add("Test.100");
alphaNumericList.add("Test.99");
Map<String, List<Integer>> map = new HashMap<>();
for (String val : alphaNumericList) {
String key = val.split("\\.")[0];
Integer value = Integer.valueOf(val.split("\\.")[1]);
if (map.containsKey(key)) {
map.get(key).add(value);
} else {
List<Integer> intList = new ArrayList<>();
intList.add(value);
map.put(key, intList);
}
}
for (Map.Entry<String, List<Integer>> entry : map.entrySet()) {
List<Integer> valueList = entry.getValue();
Collections.sort(valueList, Collections.reverseOrder());
System.out.print(entry.getKey() + "." + valueList.get(0) + " ");
}
}
Using stream and toMap() collector.
Map<String, Long> result = alphaNumericList.stream().collect(
toMap(k -> k.split("\\.")[0], v -> Long.parseLong(v.split("\\.")[1]), maxBy(Long::compare)));
The result map will contain word part as a key and maximum number as a value of the map(in your example the map will contain {Demo=1000, Test=100})
a. Assuming there are string of type Demo. and Test. in your arraylist.
b. It should be trivial to filter out elements with String Demo. and then extract the max integer for same.
c. Same should be applicable for extracting out max number associated with Test.
Please check the following snippet of code to achieve the same.
Set<String> uniqueString = alphaNumericList.stream().map(c->c.replaceAll("\\.[0-9]*","")).collect(Collectors.toSet());
Map<String,Integer> map = new HashMap<>();
for(String s:uniqueString){
int max= alphaNumericList.stream().filter(c -> c.startsWith(s+".")).map(c -> c.replaceAll(s+"\\.","")).map(c-> Integer.parseInt(c)).max(Integer::compare).get();
map.put(s,max);
}
would like to seek for advice on the following piece of code modified from an example came across.
I was wondering whether the output sequence in the resulting Map would change when the input List element sequence is changed. However, it seems the output is the same in all cases (I have run the program repeatedly on IDE). May I seek for advice on whether the order of the resulting Map elements can be expected?
Will there be any difference in sequence (alphabetical/non-alphbetical?) when using enum or String, or the element sequence is simply random?
public class TestCountry {
public enum Continent {ASIA, EUROPE}
String name;
Continent region;
public TestCountry (String na, Continent reg) {
name = na;
region = reg;
}
public String getName () {
return name;
}
public Continent getRegion () {
return region;
}
public static void main(String[] args) {
List<TestCountry> couList1 = Arrays.asList (
new TestCountry ("Japan", TestCountry.Continent.ASIA),
new TestCountry ("Italy", TestCountry.Continent.EUROPE),
new TestCountry ("Germany", TestCountry.Continent.EUROPE));
List<TestCountry> couList2 = Arrays.asList (
new TestCountry ("Italy", TestCountry.Continent.EUROPE),
new TestCountry ("Japan", TestCountry.Continent.ASIA),
new TestCountry ("Germany", TestCountry.Continent.EUROPE));
Map<TestCountry.Continent, List<String>> mapWithRegionAsKey1 = couList1.stream ()
.collect(Collectors.groupingBy (TestCountry ::getRegion,
Collectors.mapping(TestCountry::getName, Collectors.toList())));
Map<String, List<Continent>> mapWithNameAsKey1 = couList1.stream ()
.collect(Collectors.groupingBy (TestCountry::getName,
Collectors.mapping(TestCountry::getRegion, Collectors.toList())));
Map<TestCountry.Continent, List<String>> mapWithRegionAsKey2 = couList2.stream ()
.collect(Collectors.groupingBy (TestCountry ::getRegion,
Collectors.mapping(TestCountry::getName, Collectors.toList())));
Map<String, List<Continent>> mapWithNameAsKey2 = couList2.stream ()
.collect(Collectors.groupingBy (TestCountry::getName,
Collectors.mapping(TestCountry::getRegion, Collectors.toList())));
System.out.println("Value of mapWithRegionAsKey1 in couList1: " + mapWithRegionAsKey1);
System.out.println("Value of mapWithNameAsKey1 in couList1: " + mapWithNameAsKey1);
System.out.println("Value of mapWithRegionAsKey2 in couList2: " + mapWithRegionAsKey2);
System.out.println("Value of mapWithNameAsKey2 in couList2: " + mapWithNameAsKey2);
}
}
/*
* Output:
Value of mapWithRegionAsKey1 in couList1: {ASIA=[Japan], EUROPE=[Italy,
Germany]}
Value of mapWithNameAsKey1 in couList1: {Japan=[ASIA], Italy=[EUROPE],
Germany=[EUROPE]}
Value of mapWithRegionAsKey2 in couList2: {ASIA=[Japan], EUROPE=[Italy,
Germany]}
Value of mapWithNameAsKey2 in couList2: {Japan=[ASIA], Italy=[EUROPE],
Germany=[EUROPE]}
*/
Collectors.groupingBy() currently returns a HashMap. This is an implementation detail that can change in future versions.
The entries of a HashMap are not sorted, but the order in which they are iterated (when printing the HashMap) is deterministic, and doesn't depend on insertion order.
Therefore you see the same output, regardless of the order of the elements in the input List. You shouldn't rely on that order, though, since it's an implementation detail.
If you care about the order of the entries in the output Map, you can modify the code to produce a LinkedHashMap (where the default order is insertion order) or a TreeMap (where the keys are sorted).
BTW, if you change your input to
List<TestCountry> couList1 = Arrays.asList (
new TestCountry ("Japan", TestCountry.Continent.ASIA),
new TestCountry ("Italy", TestCountry.Continent.EUROPE),
new TestCountry ("Germany", TestCountry.Continent.EUROPE));
List<TestCountry> couList2 = Arrays.asList (
new TestCountry ("Germany", TestCountry.Continent.EUROPE),
new TestCountry ("Italy", TestCountry.Continent.EUROPE),
new TestCountry ("Japan", TestCountry.Continent.ASIA)
);
you will get a different order in the output:
Value of mapWithRegionAsKey1 in couList1: {ASIA=[Japan], EUROPE=[Italy, Germany]}
Value of mapWithNameAsKey1 in couList1: {Japan=[ASIA], Italy=[EUROPE], Germany=[EUROPE]}
Value of mapWithRegionAsKey2 in couList2: {ASIA=[Japan], EUROPE=[Germany, Italy]}
Value of mapWithNameAsKey2 in couList2: {Japan=[ASIA], Italy=[EUROPE], Germany=[EUROPE]}
This results from the fact that the elements of the individual output Lists (which are ArrayLists in the current implementation) are ordered according to insertion order, which depends on the ordering of your input List.
Before questioning this, read the documentation which says:
There are no guarantees on the type, mutability, serializability, or thread-safety of the Map or List objects returned.
So if you can't tell what type of the Map is returned, you can't really tell what order (if any) there will be. Well at the moment, As Eran points out it is a HashMap, but that is not guaranteed.
The question is why would you care abut this? If it for academic purposes, it makes sense, if not, collect to something that does guarantee the order.
Collectors.groupingBy take a parameter that allows you to specify the actual Map implementation you might need.
Java 8 is about to be released... While learning about Streams, I got into a scenario about grouping anagrams using one of the new ways. The problem I'm facing is that I can't find a way to group Strings objects using the map/reduce functions. Instead, I had to create a similar way as documented at Aggregate Operations - Reduction.
Based on the documentation, we can simply use:
LIST<T>.stream().collect(Collectors.groupingBy(POJO::GET_METHOD))
So that Collectors.groupingBy() will aggregate the keys of the map based on the method used. However, this approach is too seems to be cumbersome to wrap a simple String presentation.
public class AnagramsGrouping {
static class Word {
public String original;
public Word(String word) {
original = word;
}
public String getKey() {
char[] characters = input.toCharArray();
Arrays.sort(characters);
return new String(characters);
}
public String toString() {
return original;
}
}
public static void main(String[] args) {
List<Word> words = Arrays.asList(new Word("pool"), new Word("loop"),
new Word("stream"), new Word("arc"), new Word("odor"),
new Word("car"), new Word("rood"), new Word("meats"),
new Word("fires"), new Word("fries"), new Word("night"),
new Word("thing"), new Word("mates"), new Word("teams"));
Map<String, List<Word>> anagrams = words.stream().collect(
Collectors.groupingBy(Word::getKey));
System.out.println(anagrams);
}
}
This prints the following:
{door=[odor, rood], acr=[arc, car], ghint=[night, thing],
aemrst=[stream], efirs=[fires, fries], loop=[pool, loop],
aemst=[meats, mates, teams]}
Instead, I'm looking for a simpler and more direct solution that uses the new map/reduce functions to accumulate the results into the similar interface Map<String, List<String>. Based on How to convert List to Map, I have the following:
List<String> words2 = Arrays.asList("pool", "loop", "stream", "arc",
"odor", "car", "rood", "meats", "fires", "fries",
"night", "thing", "mates", "teams");
words2.stream().collect(Collectors.toMap(w -> sortChars(w), w -> w));
But this code generates a key collision as it is a Map of 1-1.
Exception in thread "main" java.lang.IllegalStateException: Duplicate key pool
which makes sense... Is there a way to group them into the similar output as the first solution with groupingBy, but without using a POJO wrapping the values?
The single-argument groupingBy collector does exactly what you want to do. It classifies its input, which you've already done using sortChars (or getKey in the earlier example). Each stream value that's classified under the same key gets put into a list which is the map's value. Thus we have:
Map<String, List<String>> anagrams =
words2.stream().collect(Collectors.groupingBy(w -> sortChars(w)));
giving the output
{door=[odor, rood], acr=[arc, car], ghint=[night, thing], aemrst=[stream],
efirs=[fires, fries], loop=[pool, loop], aemst=[meats, mates, teams]}
You could also use a method reference:
Map<String, List<String>> anagrams =
words2.stream().collect(Collectors.groupingBy(GroupingAnagrams::sortChars));
If you want to do something with the values other than building up a list, use a multi-arg overload of groupingBy and a "downstream" collector. For example, to count the words instead of building up a list, do this:
Map<String, Long> anagrams =
words2.stream().collect(
Collectors.groupingBy(GroupingAnagrams::sortChars, Collectors.counting()));
This results in:
{door=2, acr=2, ghint=2, aemrst=1, efirs=2, loop=2, aemst=3}
EDIT:
In case it wasn't clear, sortChars is simply a static function that performs a similar function to what getKey did in the first example, but from string to string:
public static String sortChars(String input) {
char[] characters = input.toCharArray();
Arrays.sort(characters);
return new String(characters);
}
You can use toMap method with four parameters and specify separately: the key type, the value type, the merge function for values with the same key, and the particular implementation of the Map into which the results will be inserted.
In this case, you can choose:
key - int[] - a sorted array of character code points of the word;
value - List<String> - a list of anagrams;
merge function - two lists into one;
map - TreeMap with a comparator that compares two int[] arrays.
List<String> words = List.of("pool", "loop", "stream", "arc", "odor", "car",
"rood", "meats", "fires", "fries", "night", "thing", "mates", "teams");
Map<int[], List<String>> anagrams = words.stream()
.collect(Collectors.toMap(
// key - a sorted array of character code points
word -> word.codePoints().sorted().toArray(),
// value - a list of anagrams
word -> new ArrayList<>(List.of(word)),
// merge elements of two lists
(list1, list2) -> {
list1.addAll(list2);
return list1;
},
// comparator that compares two int[] arrays
() -> new TreeMap<>(Arrays::compare)));
// output
anagrams.forEach((k, v) -> System.out.println(v.get(0) + "=" + v));
Output:
arc=[arc, car]
stream=[stream]
meats=[meats, mates, teams]
odor=[odor, rood]
fires=[fires, fries]
night=[night, thing]
pool=[pool, loop]
See also: How do you check if a word has an anagram that is a palindrome?
And how to add 2 enchantments at once in bukkit with
myItem.addEnchantments( Enchantment.KNOCKBACK, 1 /* TODO Here goes 2nd enchantment */ );
'addEnchantments' accepts 'addEnchantments(Map < Enchantment, int >)'
You rather use addEnchantment twice (or more):
myItem.addEnchantment(Enchantment.KNOCKBACK, 1);
myItem.addEnchantment(Enchantment.THRONS, 2);
If you insist on using addEnchantments you'll need to create a map, populate it and pass it:
Map<Enhancement, Integer> map = new HashMap<Enhancement, Integer>();
map.put(Enchantment.KNOCKBACK, 1);
map.put(Enchantment.THRONS, 2);
myItem.addEnchantments(map);
In your case, I would go with option 1
#John Smith's second question: (How to convert string to hashmap)
You can convert hashmap to string but java (as I know) doesn't have string to hashmap. You can make a function that does this (might be impossible) or make a couple functions that convert hashmap to string and string to hashmap. In this case you want a hashmap with Enchantment and an Integer, so you would simply do something like this:
public /*static*/ String hashMapToString(HashMap<Enchantment, Integer> hashMap) {
StringBuilder serializedString = new StringBuilder();
for (Enchantment enchant : hashMap.keySet()) {
serializedString.append(enchant.getName() + "<>" + hashMap.get(enchant) + ";");
}
return serializedString.toString();
}
then you would create a function to convert that back to a hashmap:
public /*static*/ HashMap<Enchantment, Integer> stringToHashMap(String hashMapString) {
HashMap<Enchantment, Integer> hashMap = new HashMap<>();
for (String split : hashMapString.split(";")) {
String[] splited = split.split("<>");
hashMap.put(Enchantment.getByName(splited[0]), Integer.valueOf(splited[1]))
}
return hashMap;
}
You can even make them static (remove the comment marks and if you don't want it at all just remove what is inside the comment marks with the comment marks)