I have a list of Strings:
List<String> terms = ["Coding is great", "Search Engines are great", "Google is a nice search engine"]
How do I get the frequency of each word in the list: Eg {Coding:1, Search:2, Engines:1, engine:1, ....}
Here is my Code:
Map<String, Integer> wordFreqMap = new HashMap<>();
for (String contextTerm : term.getContexTerms() )
{
String[] wordsArr = contextTerm.split(" ");
for (String word : wordsArr)
{
Integer freq = wordFreqMap.get(word); //this line is getting reset every time I goto a new COntexTerm
freq = (freq == null) ? 1: ++freq;
wordFreqMap.put(word, freq);
}
}
An idiomatic solution with Java 8 streams:
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class SplitWordCount
{
public static void main(String[] args)
{
List<String> terms = Arrays.asList(
"Coding is great",
"Search Engines are great",
"Google is a nice search engine");
Map<String, Integer> result = terms.parallelStream().
flatMap(s -> Arrays.asList(s.split(" ")).stream()).
collect(Collectors.toConcurrentMap(
w -> w.toLowerCase(), w -> 1, Integer::sum));
System.out.println(result);
}
}
Note that you may have to think about whether upper/lower case of the strings should play a role. This one onverts the strings to lower case, and uses them as the keys for the final map. The result is then:
{coding=1, a=1, search=2, are=1, engine=1, engines=1,
is=2, google=1, great=2, nice=1}
public static void main(String[] args) {
String msg="Coding is great search Engines are great Google is a nice search engine";
ArrayList<String> list2 = new ArrayList<>();
Map map = new HashMap();
list2.addAll((List)Arrays.asList(msg.split(" ")));
String n[]=msg.split(" ");
int f=0;
for(int i=0;i<n.length;i++){
f=Collections.frequency(list2, n[i]);
map.put(n[i],f);
}
System.out.println("values are "+map);
}
Because the answer with Java 8, while being good, does not show you how to parallel it in Java 7 (and beside default implementation is the same than stream
), here is an example:
public static void main(final String[] args) throws InterruptedException {
final ExecutorService service = Executors.newFixedThreadPool(10);
final List<String> terms = Arrays.asList("Coding is great", "Search Engines are great",
"Google is a nice search engine");
final List<Callable<String[]>> callables = new ArrayList<>(terms.size());
for (final String term : terms) {
callables.add(new Callable<String[]>() {
@Override
public String[] call() throws Exception {
System.out.println("splitting word: " + term);
return term.split(" ");
}
});
}
final ConcurrentMap<String, AtomicInteger> counter = new ConcurrentHashMap<>();
final List<Callable<Void>> callables2 = new ArrayList<>(terms.size());
for (final Future<String[]> future : service.invokeAll(callables)) {
callables2.add(new Callable<Void>() {
@Override
public Void call() throws Exception {
System.out.println("counting word");
// invokeAll implies that the future finished it work
for (String word : future.get()) {
String lc = word.toLowerCase();
// here it get tricky. Two thread might add the same word.
AtomicInteger actual = counter.get(lc);
if (null == actual) {
final AtomicInteger nv = new AtomicInteger();
actual = counter.putIfAbsent(lc, nv);
if (null == actual) {
actual = nv; // nv got added.
}
}
actual.incrementAndGet();
}
return null;
}
});
}
service.invokeAll(callables2);
service.shutdown();
System.out.println(counter);
}
Yes, Java 8 simplifies the work !
No, I tested it but don't know if it is better than simple loops nor if it perfectly threadsafe.
(And seeing how you define your list, are not coding in Groovy ? There exists parallelism support in Groovy).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.