Hi guys, Im currently working on a java project but ive come across a small minor problem. I have 4 main classes that im working with. TextReader, WordCount, WordCollecter and DisplayWords.
The TextReader class reads an input file and a method called readNextWord will return the next word from the input file. The WordCount class provides a way of keeping track of the frequency of a particular word from the input text. The WordCollector class will use the TextReader to read in the set of words contained in the input text. The DisplayWords which will display the words on the canvas.

My main problem is with the WordCollector class, here is the code i have for it so far:

    import java.util.ArrayList;
    import java.util.Collections;


    public class WordCollector
    {
        private TextReader reader;
        private ArrayList<WordCount> countWords;
        private DisplayWords display;
        private WordCount newWord;

        public WordCollector (TextReader text){
            this.reader = text;
            countWords = new ArrayList<WordCount>();
            display = new DisplayWords();
            getWordCount();
            find();
        }

        private void getWordCount(){
            while (reader.readNextWord()!=null){
                String count = reader.readNextWord();
                newWord = new WordCount(count);
                countWords.add(newWord);
            }

        }

        private WordCount find(){
            String nextWord = reader.readNextWord();
            WordCount word = new WordCount(nextWord);
            if(countWords.contains(word)){
                word.incrementCount();
                return word;
            }else{
                countWords.add(word);
            }
            Collections.sort(countWords);
            return word;
        }

        public void printReport(){
            System.out.println("there are " + countWords.size() + " words");
            for (int i=0; i<countWords.size(); i++){
                System.out.println(countWords.get(i).getText().toString() + " appears " + countWords.get(i).getCount() + " times");
            }
        }
    }

The input file for the TextReader class is the Humpty Dumpty story:
Humpty Dumpty sat on a wall,
Humpty Dumpty had a great fall.
All the king's horses and all the king's men
Couldn't put Humpty together again

When i call the PrintReport method the count doesnt work out exactly how it should be, Here is an example of the output:

there are 10 words
Text@44ac8dff appears 1 times
Text@1c9e8392 appears 1 times
Text@6acff4eb appears 1 times
Text@7ad8a715 appears 1 times
Text@25c192b5 appears 1 times
Text@4786bc70 appears 1 times
Text@5ebd81bf appears 1 times
Text@6b915330 appears 1 times
Text@11ecab7c appears 1 times
Text@48ee6315 appears 1 times

It should look like this:

There were 17 words.
humpty appeared 3 times.
dumpty appeared 2 times.
king appeared 2 times.
sat appeared 1 times.
wall appeared 1 times.
great appeared 1 times.
fall appeared 1 times.
horses appeared 1 times.
men appeared 1 times.
couldn appeared 1 times.
put appeared 1 times.
together appeared 1 times.
again appeared 1 times.

Issues that need to be sorted:
1) I need to be able to show the actual word itself and how many times it appears.
2) why am i getting hexadecimal values?

Thanks guys.

I think you're making your code way to complex.
first, TextReader should do nothing more then the name describes: it should read (and return) the text. nothing more.

then, you have in your working class a String containing the text.
use the split method to get the seperate words in an array.

create a List of words alreadyHandled, without any elements.

then, iterate over your array:

for ( String word: words){
  if ( !alreadyHandled.contains(word)){
    //count the occurences in the array
    // print the line
    System.out.println (word + " occured x times");
    alreadyHandled.add(word);
  }
}

and that's about all you need to do.

Thanks for the reply, one problem ive never really used an enhanced for loop so not sure how ( String word: words) would work. plus i was getting errors saying that the variable words was not defined.

Im a java noob :/

Edited 3 Years Ago by tukky

Text@44ac8dff appears 1 times - what's that Text@44ac8dff about?

Every Java class inherits a toString() method from the Object class, so methods like println use that to convert the object you want to print into a String. The inherited method prints the class name and the object's hash (normally the same as its address). If you want to display something more helpful, override the toString method in your Text class to return a useful string. Eg

class Person {
    private String givenName, familyName;
    ...
    @Override
    public String toString() {
        return "Person: " + givenName + " " + familyName;
    }

You should do this for every class you create so when you print an instance you get useful output.

ps: enhanced for loops - really a lot easier and safer than the old-style loops -- definitely a thing you should learn. Eg see http://www.deknight.com/java/enhanced-for-loop-in-java-5-0.html

Edited 3 Years Ago by JamesCherrill

Hey James, thats one of the problems im having with the printReport() method. its supposed to print Humpty but for some reason it prints Text@44ac8dff Ive used the toString method within the actual System.out.println line but it doesnt seem to make a difference.

Theres no toString() method anywhere in the program, not that i can find anyway.

I guess you didn't bother to read my previous post...

Every Java class inherits a toString() method from the Object class, so methods like println use that to convert the object you want to print into a String. The inherited method prints the class name and the object's hash (normally the same as its address). If you want to display something more helpful, override the toString method in your Text class to return a useful string.

I dont really understand what youre asking :/ i havent created a toString method. Although i have called it in the printReport method.
Sorry im a quite new to java so you'll have to bare with me.

Edited 3 Years Ago by tukky

OK.

Every class has a toString() method. If you don't provide it then you inherit one from the Object class. The one you inherit gives you those strings like "Text@44ac8dff".

toString() is automatically used by print to get a String version of anything you want to print. If you want something more friendly than Text@44ac8dff then you provide your own toString() for your class.

Take another look at the example I gave earler for a Person class. You need to add a method like that (exactly the same name and return type) for your Text class. In it you should return somnething that makes sense to you - eg if the Text class has a variable that holds the word, then that's what you should return.

Just to clear something up. If the toString() method was to return something that makes sense to me, wouldnt I need to know whats in the Array? Is it assuming i know that the Humpty Dumpty file is read in?
What if i had another file read in that had completely differnt text?

Sorry im just really really confused.

You haven't posted the Text class, but I'm guessing that has an instance variable with the word/text for each instance? It like my Person example - the Person class has givenName and familyName vaiables, so that's what its toString() returns.

Theres a textReader class and a Text class:

TextReader class:

import java.io.*;
import java.util.Scanner;
import java.util.Set;
import java.util.HashSet;

public class TextReader
{
    // instance variables 
    private String file;
    private Scanner s;
    private Set<String> stopWords;


    public TextReader(String file)
    {
        stopWords = new HashSet<String>();
        try {
            initialiseStopWords();
            s = new Scanner(new BufferedReader(new FileReader(file)));
            s.useDelimiter("[^a-zA-Z0-9]+");
        } catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

    private void initialiseStopWords() throws FileNotFoundException{
        Scanner s = new Scanner(new BufferedReader(new FileReader("StopWords.txt")));
        s.useDelimiter(",");
        while (s.hasNext()) {
            stopWords.add(s.next());
        }
    }

    /**
     * Read the next word from the input.  Common English "stop" words are ignored.
     * @return the next word from the input.  When there is no more input, this
     * method will return null.
     */
    public String readNextWord() {
        while (s.hasNext()) {
            String word = s.next().toLowerCase();
            if (!stopWords.contains(word) && word.length() > 1) {
                return word;
            }
        }
        return null;
    }

}

and the Text class:

import java.awt.GraphicsEnvironment;
import java.awt.GraphicsConfiguration;
import java.awt.Font;

public class Text
{
    // instance variables - replace the example below with your own
    private int leftX, leftY;
    private String text;
    private int fontSize;
    private String color;
    private String fontName;
    private boolean isVisible;
    private Font font;

    /**
     * Constructor for objects of class Text.
     * @param text a bit of text.
     */
    public Text(String text)
    {
        // initialise instance variables
        this.text = text;
        leftX = 50;
        leftY = 100;
        fontSize = 12;
        color = "black";
        fontName = "Arial";
        isVisible = false;
        setFont();
    }

    private void setFont() {
        font = new Font(fontName, Font.PLAIN, fontSize);
    }

    /**
     * Draw a graphical representation of the text on the canvas.
     * If it was already visible, do nothing.
     */
    public void makeVisible() {
        isVisible = true;
        draw();
    }

    /**
     * Erase the graphical representation of the text on the canvas.
     * If it was already invisible, do nothing.
     */
    public void makeInvisible() {
        erase();
        isVisible = false;
    }

    /**
     * Reposition the text horizontally across the canvas by a 
     * measure of 20.
     */
    public void moveRight() {
        moveHorizontal(20);
    }

    /**
     * Reposition the text horizontally across the canvas by a 
     * measure of -20.
     */
    public void moveLeft() {
        moveHorizontal(-20);
    }

    /**
     * Reposition the text vertically by a measure of -20.
     */
    public void moveUp() {
        moveVertical(-20);
    }

    /**
     * Reposition the text vertically by a measure of 20.
     */
    public void moveDown() {
        moveVertical(20);
    }

    /**
     * Reposition the text horizontally across the canvas by a given amount.
     * @param distance The amount by which to move the text.
     */
    public void moveHorizontal(int distance) {
        erase();
        leftX = leftX + distance;
        draw();
    }

    /**
     * Reposition the text vertically across the canvas by a given amount.
     * @param distance The amount by which to move the text.
     */
    public void moveVertical(int distance) {
        erase();
        leftY = leftY + distance;
        draw();
    }

    /**
     * Slowly move the text horizontally across the canvas by a 
     * given amount.  The movement across the canvas will be visible. 
     * @param distance The amount by which to move the text.
     */
    public void slowMoveHorizontal(int distance)
    {
        int delta;

        if(distance < 0) 
        {
            delta = -1;
            distance = -distance;
        }
        else 
        {
            delta = 1;
        }

        for(int i = 0; i < distance; i++)
        {
            leftX += delta;
            draw();
        }
    }

    /**
     * Slowly move the text vertically across the canvas by a 
     * given amount.  The movement across the canvas will be visible. 
     * @param distance The amount by which to move the text.
     */
    public void slowMoveVertical(int distance)
    {
        int delta;

        if(distance < 0) 
        {
            delta = -1;
            distance = -distance;
        }
        else 
        {
            delta = 1;
        }

        for(int i = 0; i < distance; i++)
        {
            leftY += delta;
            draw();
        }
    }

    /**
     * Change the font size of the text to a given value. 
     * The value of newSize must be >= 0.
     * @param newSize the new font size of the text.
     */
    public void changeSize(int newSize)
    {
        erase();
        fontSize = newSize;
        setFont();
        draw();
    }

    /**
     * Change the color. Valid colors are "red", "yellow", "blue", 
     * "green", "magenta", "pink", "orange", "cyan" and "black".
     * @param newColor the name of the new colour.
     */
    public void changeColor(String newColor)
    {
        color = newColor;
        draw();
    }

    /**
     * Print the names of all the available fonts.
     */
    public void printFonts() {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        String[] names = ge.getAvailableFontFamilyNames();
        for (String name : names ) {
            System.out.println(name);
        }
    }

    /**
     * Change the font. Valid font names can be found by calling printFonts().
     * @param newFontName the name of the new font family.
     */
    public void changeFont(String newFontName)
    {
        fontName = newFontName;
        setFont();
        draw();
    }

    /**
     * @return The X coordinate of the left of the text on the canvas.
     */
    public int getXPosition() {
        return leftX;
    }

    /**
     * @return The Y coordinate of the left of the text on the canvas.
     */
    public int getYPosition() {
        return leftY;
    }

    /**
     * @return the size of the font.
     */
    public int getFontSize() {
        return fontSize;
    }

    /**
     * @return the text itself.
     */
    public String getText() {
        return text;
    }

    /**
     * The name of the current font.
     */
    public String getFontName() {
        return fontName;
    }

    /**
     * Set the left edge of the text using the coordinates of the supplied point.
     * @param xPos the new X coordinate of the left edge of the text
     * @param yPos the new Y coordinate of the left edge of the text
     */
    public void setPosition(int xPos, int yPos) {
        Point p = new Point(xPos, yPos);
        erase();
        leftX = p.getX();
        leftY = p.getY();
        draw();
    }

    /**
     * Reposition the text at a new, random position on the canvas.
     */
    public void randomizePosition() {
        Point p = new Point();
        positionOnCanvas(p.getX(), p.getY());
    }

    public void positionOnCanvas(int x, int y) {
        Canvas c = Canvas.getCanvas();
        // If the text fits in the window, 
        // Make sure the text doesn't go off the screen
        // iff off the left, put it at the left (x=0)
        if (x < 0) x = 0;
        // if of the top, make it just fit below the top (y=0)
        if (y-this.getTextHeight() < 0) y = this.getTextHeight();
        if (c.getTextWidth(font, text) < c.getWidth()) {
            // if its off the right, put it at the right
            int rightX = x + c.getTextWidth(font, text);
            if (rightX > c.getWidth())
            {
                x = (x - (rightX - c.getWidth()));
            }
        }
        if (c.getTextHeight(font, text) < c.getHeight()) {
            // if its off the bottom of the canvas
            if (y > c.getHeight())
            {
                // put it on the bottom of the canvas
                y = c.getHeight();
            }
        }
        this.setPosition(x, y);
    }

    /**
     * Find the width of the text in the selected font.
     * @return the width of the text
     */
    public int getTextWidth() {
        Canvas c = Canvas.getCanvas();
        return c.getTextWidth(font, text);
    }

    /**
     * Find the height of the text in the selected font.
     * @return the height of the text
     */
    public int getTextHeight() {
        Canvas c = Canvas.getCanvas();
        return c.getTextHeight(font, text);
    }

    /**
     * Draw the text with current specifications on the canvas.
     */
    private void draw()
    {
        if(isVisible) {
            Canvas canvas = Canvas.getCanvas();
            canvas.draw(this, color);
            canvas.wait(10);
        }
    }

    /**
     * Erase the text on the canvas.
     */
    private void erase()
    {
        if(isVisible) {
            Canvas canvas = Canvas.getCanvas();
            canvas.erase(this);
        }
    }

}

Edited 3 Years Ago by tukky

There you go! The Text class has a variable called "text" that presumably holds the "humpty" or "dumpty" or whatever. That's what you can return from toString, so one of those values is what you will see when you print a Text object

Ah thanks a lot!! it works! :D
Now its all about getting the count to work correctly.

This question has already been answered. Start a new discussion instead.