Count number of frequency of objects that have the same value [duplicate] - java

This question already has answers here:
How to count the number of occurrences of an element in a List
(25 answers)
Closed 1 year ago.
For example i have a list:
ArrayList<Observer> arrlist = new ArrayList<Observer>();
The list contains the observer objects
but i want to know the frequency of objects that have the same value for example String name
public class Observer{
private String name;
}
How do i do that?

You basically need to iterate over the observers and count the occurence for each key (could be just a single property or a combination depending on your needs).
Taking your example of the key just being Observer.name you could do the following:
Map<String, List<Observer>> observersByName =
arrlist.stream().collect(Collectors.groupingBy(Observer::getName));
Then iterate over the entry set and call size() on the value lists to get the frequency.
If you directly want to get the frequency, add a counting() collector:
Map<String, Long> nameFrequency = arrlist.stream().collect(
Collectors.groupingBy(Observer::getName,
Collectors.counting()));
If you want to get the frequency without using streams you could use the Map.merge() method:
Map<String, Integer> nameFrequency = new HashMap<>();
for( Observer obs : arrlist ) {
//use the name as the key, associate a value of 1 with each key
//if an entry already existed merge existing and new value by summing them
frequency.merge( obs.getName(), 1, Integer::sum);
}

Related

How to access a single ArrayList in ArrayListMultiMap

I would like to get an entry from ArrayList in an ArrayListMultiMap. I am using Google Guava ArrayListMultimap and each key is associated with multiple array lists. For example, for the key1 I have 4 array lists, and each ArrayList contains 2 entries. I need to be able to access a particular ArrayList and get an entry from there so my question is how do I do it? Every time I try to access the value associated with the key it prints all 4 array lists but I need only one.
Multimap<String, ArrayList<String>> wordAsKey = ArrayListMultimap.create();
for (DictionaryEntries dict : DictionaryEntries.values()) {
ArrayList<String> list = new ArrayList<>();
String key = dict.getKey();
String partOfSpeech = dict.getPartOfSpeech();
String definition = dict.getDefinition();
list.add(partOfSpeech);
list.add(definition);
wordAsKey.put(key, list);
}
ArrayList<String> resultList = new ArrayList<>();
resultList.add(wordAsKey.get(word).toString());
System.out.println(resultList);
Prints
[[[noun, A set of pages.], [noun, A written work published in printed or electronic form.], [verb, To arrange for someone to have a seat on a plane.], [verb, To arrange something on a particular date.]]]
But I need it to print only [noun, A set of pages.]
you can try: get index value
int index = 0;
resultList.add(wordAsKey.get(word).get(index).toString());
Just do it like this -
ArrayList<String> list = (ArrayList<String>)wordAsKey.get(word);
String result = list.get(index);
System.out.println(result);
And you can check whether particular String is exist or not in List, then see below;
if(list.contains("search")){...}

how to get key and how to add more values? [duplicate]

This question already has answers here:
HashMap with multiple values under the same key
(21 answers)
Closed 4 years ago.
public static void main(String[] args) {
// write your code here
LinkedHashMap<String,String>category1=new LinkedHashMap();
category1.put("action","die hard");
Scanner s=new Scanner(System.in);
String answer=s.nextLine();
if (category1.containsKey(answer))
System.out.println(category1.get("action"));
if (category1.containsValue(answer))
System.out.println(category1.keySet());
How to get the key when the user answer with it's specific value, and how to add more values to one key?
1. The map collection, does not support multiple values under the same key, it will override whatever was stored there before.
2. However, you can change it from <String,String> to <String,List<String>>, thus gaining the ability to accumulate the answers from the client into the list. The key will refer to only one object, the list of Strings, but the list itself can hold many values.
3. In order to add more Strings to the list, you will need to retrieve the list by the desired key, and then add your new String to it.
Here is some code that implements the idea:
private void test(){
Map<String, List<String>> categories = new HashMap<>();
String answerFromClient = "Some text";
List<String> actionAnswers = categories.get("action");
if (actionAnswers == null){
actionAnswers = new ArrayList<>();
actionAnswers.add(answerFromClient);
categories.put("action",actionAnswers);
}
else{
actionAnswers.add(answerFromClient);
}
}

Merging n number of list into a Map based on a value in List

I have the following objects in an ArrayList and a value in this object is illustrated as the numbers at the beginning, which are Id of something.
I need to create a Map object, whose key should be the id of objects and whose values should be the objects with id. At the end of the day, I would like to have a Map something like that.
I have already solved this problem with two for loops and lots of if statements but it seems very ugly to me.
Any cleaner solution would be appreciated.
Map<Integer, List<Foo>> result = list.stream().collect(Collectors.groupingBy(Foo::getId));
Edited to fit the question edit, it is as simple as this:
ArrayList<Element> list = ...;
HashMap<Integer, List<Element>> map = new HashMap<Integer, List<Element>>();
for(Element e : list) {
ArrayList<Element> auxList;
if(map.contains(e.getId()) {
auxList = map.get(e.getId());
} else {
auxList = new ArrayList<Element>();
map.put(e.getId(), auxList);
}
auxList.add(e);
}
Just iterate over the starting list and add the elements to the map. If the map already contains the id, add it to the list. If not, create a new list.

Bug in HashMap / ArrayList or wrong code? [duplicate]

This question already has answers here:
ArrayList as key in HashMap
(9 answers)
Closed 6 years ago.
Tired up with trying to resolve the problem with this code:
public class MapTest {
static class T{
static class K{}
}
static Map<List<T.K>, List<String>> map = new HashMap<>();
static List<String> test(List<T.K> list, String s){
List<String> l = map.get(list);
if (l == null){
l = new ArrayList<String>();
System.out.println("New value()");
map.put(list, l);
}
l.add(s);
return l;
}
public static void main(String s[]){
ArrayList<T.K> list = new ArrayList<T.K>();
test(list, "TEST");
list.add(new T.K());
List<String> l = test(list, "TEST1");
System.out.println(l.size());
}
}
It should create a new list-value for the map only once, but output is as follows:
New value
New value
1
it is something wrong happen with hashcode of the list after I insert value in it.
I expect "new value" show up only once, and size will be 2, not 1.
is it just JVM problem or something more general?
mine one is Oracle JVM 1.8.0_65
The hashcode of the list object changes when you put an item in it. You can see how the hashcode is calculated in the ArrayList.hashCode documentation.
In general, using a mutable object as the key for a map isn't going to work well. Per the Map documentation:
Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
Thus, when you add the list to the map a second time, the map doesn't see it as being "equal" to the first list (since it isn't according to .equals), so it adds it again.
If you want a map where keys are looked up by identity rather than by value, you can use the IdentityHashMap class.

Map Entry conversion with Map Tree

So what I have been trying to do is use a TreeMap I previously had and apply it to this method in which I convert it into a set and have it go through a Map Entry Loop. What I wish to do is invert my previous TreeMap into the opposite (flipped) TreeMap
'When I run my code, it gives me a comparable error. Does this mean I have to implement the comparable method? I convereted the arrayList into an Integer so I thought the comparable method would support it. Or is it just something wrong with my code
Error: Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Comparable
Overview: Originally, my intended purpose for the program was to make a Treemap that read from a text document and specifically found all the words and the index/rows of where the words were located. Now I wish to make a "top ten" list that contains the most used words. I wanted to "flip" my treemap so that the integer values would be what would be put in order and the string would follow
public static void getTopTenWords(TreeMap<String, ArrayList<Integer>> map) {
Set<Map.Entry<String, ArrayList<Integer>>> set = map.entrySet();
TreeMap<Integer, String> temp = new TreeMap<Integer, String>();
int count = 1;
for(Map.Entry<String, ArrayList<Integer>> entry : set){
if(temp.containsKey(entry.getValue())) {
Integer val = entry.getValue().get(count);
val++;
temp.put(val, entry.getKey());
}
else {
temp.put(entry.getValue().get(count), entry.getKey());
}
count++;
}
}
Now I wish to make a "top ten" list that contains the most used words.
I wanted to "flip" my treemap so that the integer values would be what
would be put in order and the string would follow
Note that a Map contains only unique keys. So, if you try to keep your count as key, then you would need to put it in your Map by creating a new object with new Integer(count).
If you put your count in Map like: - map.put(2, "someword"), then there are chances that your previous count value gets overwritten, because Integer caches the values in range: - [-128 to 127]. So, the integer values between these range will be interned if you don't create a new object. And hence two Integer with value say 2 will point to same Integer object, and hence resulting in duplicate key.
Secondly, in your code: -
if (temp.containsKey(entry.getValue()))
using the above if statement, you are comparing an ArrayList with an Integer value. temp contains key which are integers. And values in entry are ArrayList. So, that will fail at runtime. Also, since your orginal Map contains just the location of the word found in the text file. So, just what you need to do is, get the size of arraylist for each word, and make that a key.
You would need to modify your code a little bit.
public static void getTopTenWords(TreeMap<String, ArrayList<Integer>> map) {
Set<Map.Entry<String, ArrayList<Integer>>> set = map.entrySet();
TreeMap<Integer, String> temp = new TreeMap<Integer, String>();
for(Map.Entry<String, ArrayList<Integer>> entry : set) {
int size = entry.getValue().size();
int word = entry.getKey();
temp.put(new Integer(size), word));
}
}
So, you can see that, I just used the size of the values in your entry set. And put it as a key in your TreeMap. Also using new Integer(size) is very important. It ensures that every integer reference points to a new object. Thus no duplication.
Also, note that, your TreeMap sorts your Integer value in ascending order. Your most frequent words would be somewhere at the end.

Categories