Alright, so my problem here right now is that I can get all the words from a list, find the occurrence and then add key and value pairs to map, but since I need to return a list of words which frequency is even, I get stuck. Any help?
public static List<String> onlyEvenWordsList(List<String> words) {
Map<String, Integer> wordsWithCount = new HashMap<>();
List<String> onlyEvenWords = new ArrayList<>();
for (String word : words) {
Integer count = wordsWithCount.get(word);
if (count == null) {
count = 0;
}
wordsWithCount.put(word, count + 1);
}
for(Integer value: wordsWithCount.values()){
if(value % 2 == 0){
....
}
}
return onlyEvenWords;
}
public static List<String> onlyEvenWordsList(List<String> words) {
Map<String, Integer> wordsWithCount = new HashMap<>();
List<String> onlyEvenWords = new ArrayList<>();
for (String word : words) {
Integer count = wordsWithCount.get(word);
if (count == null) {
count = 0;
}
wordsWithCount.put(word, count + 1);
}
for(Map.Entry<String, Integer> entry: wordsWithCount.entrySet()){
if(entry.getValue()%2==0){
onlyEvenWords.add(entry.getKey());
}
}
return onlyEvenWords;
}
And to print the list in main
System.out.println(Arrays.toString( onlyEvenWordsList(words).toArray()));
I have a Hashmap that has multiple pair.
As an example:
Map<String, List<String>> map = new HashMap<>();
{name}- key
{abc, dfc, ghj}- values
{address}- key
{ghj,uio,opd}-values
As per TestNg, i want this map to be used in DataProvider annotation and return me an Object[][] which can be used further in the Test in the following manner:
{{"name,abc"},{"name,dfc"}....}
Apologies for not mentioning the solution i tried, here it goes:
String[] keys = new String[map.size()];
ArrayList<ArrayList<String>> values = new ArrayList<>();
int index = 0;
for (Map.Entry<String, List<String>> mapEntry : map.entrySet()) {
keys[index] = mapEntry.getKey();
values[index] = mapEntry.getValue();
index++;
}
Create a helper-class:
private class Pair {
public String key, value;
}
your code:
Map<String, List<String>> map = new HashMap<>();
List<Pair> pairs = new ArrayList();
for(Map.Entry<String, List<String>> entry : map.entrySet())
{
for(String value : entry.getValue())
{
Pair newPair = new Pair();
newPair.key = entry.getKey();
newPair.value = value;
pairs.add(newPair);
}
}
I have a Input String as :
String str="1,1,2,2,2,1,3";
I want count each id occurrence and store them into List,and I want output Like this:
[
{
"count": "3",
"ids": "1, 2"
}
{
"count": "1",
"ids": "3"
}
]
I tried by using org.springframework.util.StringUtils.countOccurrencesOf(input, "a"); like this. But after counting not getting the things like I want.
This will give you the desired result. You first count the occurrences of each character, then you group by count each character in a new HashMap<Integer, List<String>>.
Here's a working example:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Test {
public static void main(String[] args) {
String str = "1,1,2,2,2,1,3";
String[] list = str.split(",");
HashMap<String, Integer> occr = new HashMap<>();
for (int i = 0; i < list.length; i++) {
if (occr.containsKey(list[i])) {
occr.put(list[i], occr.get(list[i]) + 1);
} else {
occr.put(list[i], 1);
}
}
HashMap<Integer, List<String>> res = new HashMap<>();
for (String key : occr.keySet()) {
int count = occr.get(key);
if (res.containsKey(count)) {
res.get(count).add(key);
} else {
List<String> l = new ArrayList<>();
l.add(key);
res.put(count, l);
}
}
StringBuffer sb = new StringBuffer();
sb.append("[\n");
for (Integer count : res.keySet()) {
sb.append("{\n");
List<String> finalList = res.get(count);
sb.append("\"count\":\"" + count + "\",\n");
sb.append("\"ids\":\"" + finalList.get(0));
for (int i = 1; i < finalList.size(); i++) {
sb.append("," + finalList.get(i));
}
sb.append("\"\n}\n");
}
sb.append("\n]");
System.out.println(sb.toString());
}
}
EDIT: A more generalised solution
Here's the method that returns a HashMap<Integer,List<String>>, which contains the number of occurrences of a string as a key of the HashMap where each key has a List<String> value which contains all the strings that occur key number of times.
public HashMap<Integer, List<String>> countOccurrences(String str, String delimiter) {
// First, we count the number of occurrences of each string.
String[] list = str.split(delimiter);
HashMap<String, Integer> occr = new HashMap<>();
for (int i = 0; i < list.length; i++) {
if (occr.containsKey(list[i])) {
occr.put(list[i], occr.get(list[i]) + 1);
} else {
occr.put(list[i], 1);
}
}
/** Now, we group them by the number of occurrences,
* All strings with the same number of occurrences are put into a list;
* this list is put into a HashMap as a value, with the number of
* occurrences as a key.
*/
HashMap<Integer, List<String>> res = new HashMap<>();
for (String key : occr.keySet()) {
int count = occr.get(key);
if (res.containsKey(count)) {
res.get(count).add(key);
} else {
List<String> l = new ArrayList<>();
l.add(key);
res.put(count, l);
}
}
return res;
}
You need to do some boring transfer, I'm not sure if you want to keep the ids sorted. A simple implementation is:
public List<Map<String, Object>> countFrequency(String s) {
// Count by char
Map<String, Integer> countMap = new HashMap<String, Integer>();
for (String ch : s.split(",")) {
Integer count = countMap.get(ch);
if (count == null) {
count = 0;
}
count++;
countMap.put(ch, count);
}
// Count by frequency
Map<Integer, String> countByFrequency = new HashMap<Integer, String>();
for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
String chars = countByFrequency.get(entry.getValue());
System.out.println(entry.getValue() + " " + chars);
if (chars == null) {
chars = "" + entry.getKey();
} else {
chars += ", " + entry.getKey();
}
countByFrequency.put(entry.getValue(), chars);
}
// Convert to list
List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
for (Map.Entry<Integer, String> entry : countByFrequency.entrySet()) {
Map<String, Object> item = new HashMap<String, Object>();
item.put("count", entry.getKey());
item.put("ids", entry.getValue());
result.add(item);
}
return result;
}
Hey check the below code, it help you to achieve your expected result
public class Test
{
public static void main(String args[])
{
String str = "1,1,2,2,2,1,3"; //Your input string
List<String> listOfIds = Arrays.asList(str.split(",")); //Splits the string
System.out.println("List of IDs : " + listOfIds);
HashMap<String, List<String>> map = new HashMap<>();
Set<String> uniqueIds = new HashSet<>(Arrays.asList(str.split(",")));
for (String uniqueId : uniqueIds)
{
String frequency = String.valueOf(Collections.frequency(listOfIds, uniqueId));
System.out.println("ID = " + uniqueId + ", frequency = " + frequency);
if (!map.containsKey(frequency))
{
map.put(frequency, new ArrayList<String>());
}
map.get(frequency).add(uniqueId);
}
for (Map.Entry<String, List<String>> entry : map.entrySet())
{
System.out.println("Count = "+ entry.getKey() + ", IDs = " + entry.getValue());
}
}
}
One of the approach i can suggest you is to
put each "character" in hashMap as a key and "count" as a value.
Sample code to do so is
String str = "1,1,2,2,2,1,3";
HashMap<String, String> map = new HashMap();
for (String c : str.split(",")) {
if (map.containsKey( c)) {
int count = Integer.parseInt(map.get(c));
map.put(c, ++count + "");
} else
map.put(c, "1");
}
System.out.println(map.toString());
}
<!--first you split string based on "," and store into array, after that iterate array end of array lenght in side loop create new map and put element in map as a Key and set value as count 1 again check the key and increase count value in map-->
like....
String str="1,1,2,2,2,1,3";
String strArray=str.split(",");
Map strMap= new hashMap();
for(int i=0; i < strArray.length(); i++){
if(!strMap.containsKey(strArray[i])){
strMap.put(strArray[i],1)
}else{
strMap.put(strArray[i],strMap.get(strArray[i])+1)
}
}
String str="1,1,2,2,2,1,3";
//Converting given string to string array
String[] strArray = str.split(",");
//Creating a HashMap containing char as a key and occurrences as a value
Map<String,Integer> charCountMap = new HashMap<String, Integer>();
//checking each element of strArray
for(String num :strArray){
if(charCountMap.containsKey(num))
{
//If char is present in charCountMap, incrementing it's count by 1
charCountMap.put(num, charCountMap.get(num)+1);
}
else
{
//If char is not present in charCountMap, and putting this char to charCountMap with 1 as it's value
charCountMap.put(num, 1);
}
}
//Printing the charCountMap
for (Map.Entry<String, Integer> entry : charCountMap.entrySet())
{
System.out.println("ID ="+entry.getKey() + " count=" + entry.getValue());
}
}
// Split according to comma
HashMap<String, Integer> hm = new HashMap<String, Integer>();
for (String key : tokens) {
if (hm.containsKey(key)) {
Integer currentCount = hm.get(key);
hm.put(key, ++currentCount);
} else {
hm.put(key, 1);
}
}
// Organize info according to ID
HashMap<Integer, String> result = new HashMap<Integer, String>();
for (Map.Entry<String, Integer> entry : hm.entrySet()) {
Integer newKey = entry.getValue();
if (result.containsKey(newKey)) {
String newValue = entry.getKey() + ", " + result.get(newKey);
result.put(newKey, newValue);
} else {
result.put(newKey, entry.getKey());
}
}
And here is a complete Java 8 streaming solution for the problem. The main idea is to first build a map of the occurances of each id, which results in:
{1=3, 2=3, 3=1}
(first is ID and second the count) and then to group by it by the count:
public static void main(String[] args) {
String str = "1,1,2,2,2,1,3";
System.out.println(
Pattern.compile(",").splitAsStream(str)
.collect(groupingBy(identity(), counting()))
.entrySet().stream()
.collect(groupingBy(i -> i.getValue(), mapping( i -> i.getKey(), toList())))
);
}
which results in:
{1=[3], 3=[1, 2]}
This is the most compact version I could come up with. Is there anything even smaller?
EDIT: By the way here is the complete class, to get all static method imports right:
import static java.util.function.Function.identity;
import java.util.regex.Pattern;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toList;
public class Java8StreamsTest6 {
public static void main(String[] args) {
String str = "1,1,2,2,2,1,3";
System.out.println(
Pattern.compile(",").splitAsStream(str)
.collect(groupingBy(identity(), counting()))
.entrySet().stream()
.collect(groupingBy(i -> i.getValue(), mapping(i -> i.getKey(), toList())))
);
}
}
I have a list of HashMap and I want to sort it in ascending order in Java.
I am using custom Comparator to implement the logic, but its failing. Its just grouping the list based on Map keys. Its not sorting the list entirely.
My Code looks like-
public class ListMap {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
List<HashMap<String, String>> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
int value = randInt(1, 20);
long timeInMillis = cal.getTimeInMillis();
HashMap<String, String> mp = new HashMap<>();
mp.put("" + value, "Values" + value + ":" + timeInMillis);
list.add(mp);
}
Collections.sort(list, new Comparator<Map<String, String>>() {
#Override
public int compare(Map<String, String> map1,
Map<String, String> map2) {
String val1 = "";
String val2 = "";
for (Map.Entry<String, String> entry : map1.entrySet()) {
val1 = entry.getKey();
}
for (Map.Entry<String, String> entry : map2.entrySet()) {
val2 = entry.getKey();
}
return val1.compareTo(val2);
}
});
for (Map<String, String> hashMap : list) {
for (Map.Entry<String, String> entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + "/" + entry.getValue());
}
}
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
}
It prints the output-
10/Values10:1437660285301
11/Values11:1437660285301
11/Values11:1437660285301
11/Values11:1437660285301
13/Values13:1437660285301
13/Values13:1437660285301
15/Values15:1437660285301
15/Values15:1437660285301
15/Values15:1437660285301
16/Values16:1437660285301
17/Values17:1437660285301
18/Values18:1437660285301
18/Values18:1437660285301
19/Values19:1437660285301
19/Values19:1437660285301
2/Values2:1437660285301
3/Values3:1437660285301
4/Values4:1437660285301
6/Values6:1437660285301
6/Values6:1437660285301
It groups the values by key, but I want the entire sorted list like in the above example.
I was expecting 2 and then 3, then 4 and go on.
You're comparing based on the keys which are of type String. Comparison will be done lexicographically, i.e. 12 is less than 2.
You need to compare the keys as Integers in the comparator:
Collections.sort(list, new Comparator<Map<String, String>>() {
#Override
public int compare(Map<String, String> map1,
Map<String, String> map2) {
String val1 = "";
String val2 = "";
for (Map.Entry<String, String> entry : map1.entrySet()) {
val1 = entry.getKey();
}
for (Map.Entry<String, String> entry : map2.entrySet()) {
val2 = entry.getKey();
}
return Integer.valueOf(val1).compareTo(Integer.valueOf(val2));
}
});
Just modify your comparator converting the key string to an integer:
new Comparator<Map<String, String>>() {
#Override
public int compare(Map<String, String> map1,
Map<String, String> map2) {
String val1 = "";
String val2 = "";
for (Map.Entry<String, String> entry : map1.entrySet()) {
val1 = entry.getKey();
}
for (Map.Entry<String, String> entry : map2.entrySet()) {
val2 = entry.getKey();
}
int key1 = Integer.parseInt(val1);
int key2 = Integer.parseInt(val2);
return key1.compareTo(key2);
}
}
I have two hashmaps and I would like to fill a third hashmap which keys will be the values of the first hash map and the values will be the values of the second hashmap splitted to an array.
i.e.:
hashmap1 = {1=e1, 2=e2}
hashmap2 = {10=word1-word2-word3, 20=word4-word5-word6}
the result:
hashmap3 = {e1=word1-word2-word3, e2=word4-word5-word6}
This is what I did so far:
static HashMap<Integer, String> catnamecatkeys = new HashMap<Integer, String>();
static HashMap<Integer, String> keywords = new HashMap<Integer, String>();
static HashMap<String, String> tempHash = new HashMap<String, String>();
static HashMap<String, String[]> hash = new HashMap<String, String[]>();
static String[] arr;
public static void main(String[] args) {
catnamecatkeys.put(1, "e1");
catnamecatkeys.put(2, "e2");
keywords.put(1, "word1-word2-word3");
keywords.put(2, "word4-word5-word6");
for (int key : catnamecatkeys.keySet()) {
tempHash.put(catnamecatkeys.get(key),null);
}
for(String tempkey: tempHash.keySet()){
tempHash.put(tempkey,keywords.entrySet().iterator().next().getValue());
arr = tempHash.get(tempkey).split("-");
hash.put(tempkey, arr);
}
System.out.println(tempHash);
for (String hashkey : hash.keySet()) {
for (int i = 0; i < arr.length; i++) {
System.out.println(hashkey + ":" + hash.get(hashkey)[i]);
}
}
}
but the output is:
hashmap3 = {e1=word1-word2-word3, e2=word1-word2-word3}
Any Ideas please?
You should initialize Iterator outside the loop, Here is complete example -
static HashMap<Integer, String> catnamecatkeys = new HashMap<Integer, String>();
static HashMap<Integer, String> keywords = new HashMap<Integer, String>();
static HashMap<String, String> tempHash = new HashMap<String, String>();
static HashMap<String, String[]> hash = new HashMap<String, String[]>();
static String[] arr;
public static void main(String[] agrs)
{
catnamecatkeys.put(1, "e1");
catnamecatkeys.put(2, "e2");
keywords.put(1, "word1-word2-word3");
keywords.put(2, "word4-word5-word6");
for (int key : catnamecatkeys.keySet()) {
tempHash.put(catnamecatkeys.get(key),null);
}
Set<Entry<Integer,String>> set = keywords.entrySet();
Iterator<Entry<Integer, String>> iterator= set.iterator();
for(String tempkey: tempHash.keySet()){
tempHash.put(tempkey,iterator.next().getValue());
arr = tempHash.get(tempkey).split("-");
hash.put(tempkey, arr);
}
System.out.println(tempHash);
for (String hashkey : hash.keySet()) {
for (int i = 0; i < arr.length; i++) {
System.out.println(hashkey + ":" + hash.get(hashkey)[i]);
}
}
}
Your problem is this line:
keywords.entrySet().iterator().next().getValue()
is always going to return the same entry of the keywords HashMap. Try building your new hashmap with something like:
for (int i = 1; i < 3; i++) {
tempHash.put(catnamecatkeys.get(i), keywords.get(i));
}
According to your example where you have:
hashmap1 = {1=e1, 2=e2}
hashmap2 = {10=word1-word2-word3, 20=word4-word5-word6}
the result:
hashmap3 = {e1=word1-word2-word3, e2=word4-word5-word6}
There is no common key between hashmap1 and hashmap2, so we are trying to relate the value from hashmap1 with key "1" to the value in hashmap2 with key "10". There is no way to do this unless additional information about how to map the entries from hashmap1 to hashmap2 is retained. This additional information could be the insertion order into the map if a map that guarantees iteration order to be the same as insertion order is used (e.g. LinkedHashMap).