Reputation: 123
Does anyone know how can I get the following answer with the code I have?
aaa: 3
bbb: 2
ccc: 1
1: 2
2: 2
3: 1
4: 1
Here is what I've tried so far:
this is the main class
package tester1;
import java.util.ArrayList;
public class Tester1 {
public static void main(String[] args) {
tester t1 = new tester(1,"aaa");
tester t2 = new tester(2,"aaa");
tester t3 = new tester(2,"aaa");
tester t4 = new tester(1,"ccc");
tester t5 = new tester(3,"bbb");
tester t6 = new tester(4,"bbb");
ArrayList<tester> list = new ArrayList<tester>();
list.add(t1);
list.add(t2);
list.add(t3);
list.add(t4);
list.add(t5);
list.add(t6);
test t = new test(list);
t.getter();
}
}
this the the class to connect to the array list
package tester1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class test {
private ArrayList<tester> testList;
public test(ArrayList<tester> testList) {
this.testList = testList;
}
public void getter()
{
Set<tester>unique = new HashSet<tester>(testList);
for(tester key:unique)
{
System.out.println(key.getName()+": "+Collections.frequency(testList, key.getName()));
}
}
}
this class the where the constructor is
package tester1;
public class tester {
private int num;
private String name;
public tester(int num, String name) {
this.num = num;
this.name = name;
}
public int getNum() {
return num;
}
public String getName() {
return name;
}
}
Upvotes: 0
Views: 711
Reputation: 1676
Here is another version, which simplifies some part, but shows a short lambda solution with some static-imports:
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class Tester
{
public static void main(final String[] args)
{
final List<String> list = Arrays.asList("aaa", "aaa", "aaa", "ccc", "bbb", "bbb");
final Map<String, Long> map = list.stream()
.collect(groupingBy(identity(), counting()));
System.out.println("map = " + map);
}
}
Upvotes: 0
Reputation: 10852
list.stream()
.collect(Collectors.groupingBy(t -> t.getName(), Collectors.counting()))
.entrySet()
.stream()
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
.forEach(e -> System.out.println(e.getKey() + ":" + e.getValue()));
How about giving Stream
a try. You don't even need the test
class.
You can achieve it by following 2 steps below.
Upvotes: 0
Reputation: 7347
From the javadoc of Collections#frequency:
Returns the number of elements in the specified collection equal to the specified object. More formally, returns the number of elements e in the collection such that (o == null ? e == null : o.equals(e)).
So, why does it output 0 everywhere? It´s quite simple, because the given contract can never resolve to true
, as no Tester
will be equal to a String
.
in order to achive the correct output you have to override equals
and hascode
in Tester
first.
// both are generated by eclipse source generation for the field name.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Tester other = (Tester) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
Now you need to change your Collections#frequency
call to work on the Tester
and not the name
field of Tester
:
// replaced key.getName() with key
System.out.println(key.getName() + ": " + Collections.frequency(testList, key));
You will now have the proper output of (just not sorted by ammount of occurences):
bbb: 2
aaa: 3
ccc: 1
Upvotes: 2
Reputation: 5423
you can use a Map
to store the counts:
public Map<String,Integer> getCounts(ArrayList<Tester> list){
Map<String,Integer> counter=new HashMap<String,Integer>();
for(Tester s : list){
if(counter.containsKey(s.getKey())){
counter.put(s,counter.get(s.getKey())+1);
}else{
counter.put(s.getKey(),1);
}
}
return counter;
}
now To print you can simply iterate through your map:
for(Map.Entry<String,Integer> entry : getCounts(list).entrySet()){
System.out.println(entry.getKey() + " : " + entry.getValue();
}
Upvotes: 0