Reputation: 51
I have a text file which has lines of animals, who occur on this list from 1 to n times. I need to read this text file, count all the separate animal occurences, sort them from highest to lowest and put them in a jtable.
For example, the text file looks like this:
dog
sheep
cat
horse
cat
tiger
cat
cat
tiger
I need to count all the same occurences like so:
dog 1
sheep 1
cat 4
horse 1
tiger 2
And then sort them from highest to lowest and somehow put them into a table, so that would be:
Animal name: count
cat 4
tiger 2
dog 1
sheep 1
horse 1
So, for now my specific question is how can i count the matches for all the separate animals?
Thanks for the help!
The answer provided by Vishal Kamat, has worked, my animals and their occurences have been counted with this code:
java hashmap word count from a text file
Now, I just need to put all this information to a new jtable
Upvotes: 1
Views: 993
Reputation: 3559
You can do this with Java 8 Streams. This solution is compact and quite expressive. It creates a Stream of lines read from the file. Each unique line becomes a group, it counts the entries in each group, and then sorts the groups by their value, in descending order.
Now since you want to put these in a JTable, you need a two dimentional array.
package com.test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.swing.JTable;
public class TestCount {
public static void main(String args[]) throws URISyntaxException, IOException {
// for absolute path use: Paths.get("/path/to/animals.txt")
try (Stream<String> stream = Files.lines(Paths.get(TestCount.class.getClassLoader().getResource("animals").toURI()))) {
Object[][] data = stream
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map((entry) -> new Object[] { entry.getKey(), entry.getValue() })
.toArray(Object[][]::new);
// print the data
for (Object[] row : data) {
System.out.println(Arrays.toString(row));
}
// create the JTable
new JTable(data, new String[] { "animal", "count" });
}
}
}
If you already have a sorted Map you can covert to a two dimensional array like so:
Object[][] data = m1.entrySet().stream()
.map((entry) -> new Object[] { entry.getKey(), entry.getValue() })
.toArray(Object[][]::new);
Upvotes: 0
Reputation: 1209
Most of the answers here are either too complicated or don't implement frequency distribution properly. Following is my solution:
Map<String, Integer> frequency = new HashMap<>();
try (Scanner scanner = new Scanner(new File("path/to/file"), "UTF-8")) {
while (scanner.hasNext()) {
String temp = scanner.nextLine();
if(frequency.containsKey(temp)) {
Integer count = frequency.get(temp);
frequency.put(temp, Integer.sum(count, 1));
} else {
frequency.put(temp, 1);
}
}
}
The key of the Map contains the animal name and value (which is an Integer) contains the occurrences of the animal names read so far. After each iteration, check if the animal name is in the key. If yes, increment its value. Otherwise, put a new key-value pair with the value as 1. Once the Map has been populated, you can use it as you please.
Upvotes: 0
Reputation: 91
You can try this.if it is convenient to you.
HashMap map=new HashMap();
HashSet set=new HashSet();
FileInputStream fis=new FileInputStream(file);
StreamTokenizer st=new StreamTokenizer(fis);
while(st.nextToken()!=StreamTokenizer.TT_EOF){
Integer count=1;
String s;
switch(st.ttype)
{
case StreamTokenizer.TT_WORD:
s=st.sval;
if(map.containsKey(s))
{
count=(Integer)map.get(s);
count++;
map.put(s,count);
set.add(s);
}
else
{
map.put(s,count);
set.add(s);
}
break;
}
}
//now you have a collection of words with their frequency.it will automatically sort numeric values
System.out.println("frequency of each word in file");
Iterator iter=set.iterator();//get all the keys from the HashSet
//display them with help of Iterator interface
while(iter.hasNext())
{
String s=(String)iter.next();
Integer count=(Integer)map.get(s);
System.out.println("frequency of "+s+" : "+count);
}
Upvotes: 0
Reputation: 369
Just use the switch-case. You can use a counter for each animal. Or use an arrayList where you can store the amount of each animal...
String line = reader.readLine();
while (line != null) {
switch (line) {
case "cat":
catCounter++;
break;
case "dog":
dogCounter++;
break;
case "horse":
horseCounter++;
break;
case "tiger":
tigerCounter++;
break;
case "sheep":
sheepCounter++;
break;
default:
break;
}
}
Upvotes: 1
Reputation: 589
You can have a Map<String, Integer>
where key would be the animal name and count would be the occurances so far. Everytime you read an animal, get the value from the map and increment it. Finally you can sort the Map using the integer value of the count and store in the table.
Upvotes: 0
Reputation: 1
Unfortunately I'm not able to write and test a code, but I am able to give you a path to do the thing you want.
You can use Regex for matching how many times, let's say "cat" was mentioned in the text file.
Perhaps this would help: http://code.runnable.com/UqUJWzqM7L8-AAFT/how-to-count-the-number-of-matching-string-in-java-for-regex
I did not write the code, credits to Mirang.
Upvotes: 0