1

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!


EDIT

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

Stphane
  • 3,368
  • 5
  • 32
  • 47
Gediminas
  • 51
  • 6

6 Answers6

1

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;
            }
        }
Elfie
  • 374
  • 3
  • 15
  • What happens if I add a Fox? – UrsinusTheStrong May 01 '16 at 14:45
  • just add another case for the fox. I know this is not a good solution if you want to add more different animals. – Elfie May 01 '16 at 14:47
  • the other thing he could do is to check the content of the current line and store the string inside an array. For this solution write a class for example "animal" and this class has to have a String attribute for the name and an integer to count how many there are. So he just has to store instances of animal inside the array and to update the amount of each animal. So if you add another animal just create a new instance and store it in the array – Elfie May 01 '16 at 14:52
  • I think Map is a better option. See my answer. – UrsinusTheStrong May 01 '16 at 15:18
  • @UrsinusTheStrong yes you are right. the map is better than the switch case option. But if you read my comment above you will see that I wrote a second answer.. It is a object-oriented option. There you could implement Map too ;) – Elfie May 03 '16 at 06:48
0

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.

  • Thanks, this looks is kind of similar, but in the code you provided, the user has a specific line he wants to get matches for, i need to count matches for 5 or more separate strings – Gediminas May 01 '16 at 14:27
0

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.

Vishal
  • 549
  • 3
  • 13
  • Thanks! This looks like the correct solution to my problem, but to be honest, I don't know how to implement it. Do you know where i could find some examples with `Map` implemented in similar fashion to my code? – Gediminas May 01 '16 at 14:35
  • This might help you http://stackoverflow.com/questions/31288274/java-hashmap-word-count-from-a-text-file – Vishal May 01 '16 at 14:40
  • Thank you so much man! The code provided you your link works, it counted all my animals! Now i just need to sort them and put them in a jtable. – Gediminas May 01 '16 at 14:44
  • Sorry not at my computer so cannot give the exact code but this site shows how to sort based on values. http://www.mkyong.com/java/how-to-sort-a-map-in-java/ – Vishal May 01 '16 at 15:55
0

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);
Nazaret K.
  • 3,409
  • 6
  • 22
  • 31
0

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);
}
Sharad Gautam
  • 91
  • 5
  • 11
  • Here i use StreamTokenizer . it is usefull to read a file in tokens.. you do not have to split file after read..and here i also use Iterator interface it is useful when you want to iterate whole collection. – Sharad Gautam May 01 '16 at 15:09
0

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.

UrsinusTheStrong
  • 1,239
  • 1
  • 16
  • 33