Why is my contains function not detecting the element? - java

I am trying to read in a large block of text and store each unique word and the number of times it came up in the text. To do this I made an array list of a Word class. The Word class simply stores the word and number of times it came up. To avoid duplicates of the same word I use the .contains() function to see if I have already processed a word before, but for some reason, .contains() is not working.
class Main
{
public static void main(String[] args) throws FileNotFoundException
{
File file = new File("poe.text");
Scanner f = new Scanner(file);
ArrayList<Word> words = new ArrayList<Word>();
int total = 0;
while(f.hasNext())
{
Word temp = new Word(f.next().toLowerCase().trim());
//System.out.println("temp is "+temp.getWord());
total++;
if(words.contains(temp))
{
words.get(words.indexOf(temp)).up();
} else
{
words.add(temp);
}
}
for(Word w:words)
{
System.out.println(w.toString());
}
}
}
The if statement never evaluates to true and every word is added to the words ArrayList even if it is already present.

In the Javadoc for List, the contains method uses the equals() method to evaluate if two objects are the same. have you implemented equals and hashcode in your words class ?
Javadoc
http://docs.oracle.com/javase/7/docs/api/java/util/List.html#contains%28java.lang.Object%29

Related

Variable Scope - JAVA Class/Method

I am reading in data from a text file into an ArrayList and then trying to search for a particular string in that ArrayList (the second method).
I believe that I am correctly reading in the data however am struggling to write methods to implement on the ArrayList once it has been filled. For instance, in the checking method below, it is returning a false when I am certain the input String is in the data structure.
I recognize this is likely a problem with my variable scope or how my methods are interacting with each other (i.e, the arraylist is not actually filled with the data when I am checking it).
Any help would be much appreciated - thanks
import java.util.*;
import java.io.*;
public class Word {
ArrayList<String> diclist = new ArrayList<String>();
private void readIn() throws FileNotFoundException {
File file = new File("filepath");
Scanner s = new Scanner(file);
s.useDelimiter("\n");
while (s.hasNextLine()) {
diclist.add(s.nextLine());
}
s.close();
}
public boolean checkIn(String z) {//Check if input string z is in diclist
for (int i = 0; i < diclist.size(); i++) {
if (diclist.get(i).equals(z)) {return true;}
}
return false;
}
}
There are no obvious problems in the code you posted so far. After calling readIn, if the file exists, readable and not empty, the list should get populated. I suggest running it through a debugger.
Note that the checkIn method can be vastly simplified to this:
return diclist.contains(z);

Java HashSet object adding

I am trying to go through a text from a file, get each Word and save it as a Word object in a HashSet but i am alway getting the size 1 for the HashSet,it stores only the first object, i dont know maybe there is some really easy way to do it, or maybe i have made some stupid mistake here are you the code:
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\Taner\\Desktop\\words.txt");
Scanner input = new Scanner(file);
HashSet<Word> wordHash = new HashSet<>();
while (input.hasNextLine()) {
String line = input.nextLine();
for (String retval: line.split(" ", 0)){
wordTree.add(new Word(retval));
}
}
input.close();
System.out.println(wordTree);
}
This can happen if Word has a broken implementation of hashCode and equals:
it would seem that all the values added in the HashSet are the same.
Check the implementations of those methods in Word.
If you use an IDE like Eclipse or IntelliJ,
it can generate correct implementations for hashCode and equals.
I suggest you use that.

Returning the String at the index typed in by the user (ArrayList)

I'm trying to create a simple method. Basically, I want this method (called "returnIndex") to return the word at the ArrayList index number the user types in.
Example:
If the user types in "1", is should return whatever String is at index 1 in the ArrayList.
This is what I have so far:
public void returnIndex ()
{
Scanner in = new Scanner (System.in)
while (in.hasNextLine())
{
if (in.equals(1))
{
//return item at that index
}
}
}
I'm just not sure how to say "return the item at that index" in Java. Of course, I'll have to make the code work with any other number, not just '1'. But for now, I'm focusing on '1'. Not even sure if the in.equals(1) part is even 100% right.
My apologies if this question seems a little elementary. I'm still working on my Java. Just hints please, no complete answers. Thank you very much.
public String returnIndex(Scanner in, List<String> list) {
return list.get(in.nextInt());
}
Don't create new Scanners as it can cause subtle problems. Instead, create only one and keep using it. That means you should pass it into this function.
There's no need to use ArrayList when List will do (as it will here).
You need to make the function return String, not void, if you want it to return a String.
public static void main(String[] args) {
List<String> values = new ArrayList<String>();
values.add("One");
values.add("Two");
values.add("Three");
String result = getStringAtIndex(values);
System.out.println("The result:" + result);
}
public static String getStringAtIndex(List<String> list) {
Scanner scanner = new Scanner(System.in);
int index = 0;
index = scanner.nextInt();
return list.get(index-1);
}

Java class Anagrams

Im new to the java programming language and need help writing a class Anagrams that prints the permutations of words in a sentence. Example: red car -> red car, car red. This is what i have written so far and i think im on the right track and even though my code is not finished, i would at least like to get it to run.
import javax.swing.JOptionPane;
public class Anagrams
{
private String x;
private char[] xarray;
private String[] words;
public void Anagrams(String phrase1)
{
x = phrase1;
}
public void printPerms()
{
int perms = 0;
xarray = x.toCharArray();
for (int i = 0; i < x.length(); i++)
{
if(xarray[i] == ' ') perms = perms + 1;
}
words = x.split(" ");
for (int i = 0; i < perms; i++)
{
System.out.println(words[i]);
}
}
public void main(String args[])
{
String phrase1 = JOptionPane.showInputDialog("Enter phrase 1.");
Anagrams(phrase1);
printPerms();
}
}
This is the error i get when i try to run.
Exception in thread "main" java.lang.NoSuchMethodError: main
Right now im just trying to get my program to run not print out the permutations. I think i can figure that out once it at least print something out. Can someone tell me why it doesnt run and how do you get input from the user like c++ cin>>, if there is another way other than JOptionPane.
Thanks
A main method needs to be static.
How about this:
public static void main(String args[])
{
String phrase1 = JOptionPane.showInputDialog("Enter phrase 1.");
new Anagrams(phrase1).printPerms();
}
Even After Declaring your main method as static you may or may not be required to make all other methods as static(If calling methods dirctly without use of objects make methods as static).Because a static method can call or use only static data memebers or methods.
And in your code because you have defined all the methods in the same class which contains main method you need to make other methods also as static.
The method should return true if the two arguments are anagrams of each other, false if they are not.
For example, anagram(“glob”, “blog”) would return true;and anagram(“glob”, “blag”) false.
Assumes that the input strings will contain only letters and spaces. Treat upper- and lower-case letters as identical, and ignore spaces.
<br/> Uses the following algorithm:
<ul> <li> clean input strings from spaces and convert to lower case
</li> <li>convert to char array and sort them
</li> <li>if sorted arrays are identical, words are anagrams
</li></ul>
*/
public static boolean anagram(String str1, String str2)
{
//handle nulls
if(str1==null && str2==null)
return true;
else if( (str1==null && str2!=null) || (str2==null && str1!=null) )
return false;
//clean input strings from spaces and convert to lower case
String s1 = str1.replace(" ", "").toLowerCase();
String s2 = str2.replace(" ", "").toLowerCase();
//convert to char array and sort them
char[] cArr1 = s1.toCharArray();
char[] cArr2 = s2.toCharArray();
java.util.Arrays.sort(cArr1);
java.util.Arrays.sort(cArr2);
//if sorted arrays are identical, words are anagrams
s1 = new String(cArr1);
s2 = new String(cArr2);
return s1.equals(s2);
}
public static void main(String[] args)
{
//test: anagram(“glob”, “blog”) would return true; anagram(“glob”, “blag”) false.
System.out.println("anagram(“glob”, “blog”):"+(anagram("glob", "blog")));
System.out.println("anagram(“glob”, “blag”):"+(anagram("glob", "blag")));
}
You are missing static in:
public void main(String args[])
The main method needs to be static.
Also you are calling printPerms from main directly (without an object) so it must be made static as well or call them on a Anagram class object.
You are missing the new keyword while creating the object:
Anagrams(phrase1);
printPerms();
try
new Anagrams(phrase1).printPerms();
Also there is no Anagram class constructor that takes a String. What you have is a method named Anagram as you've specified the return type.
public void Anagrams(String phrase1) {
drop the void.

To have efficient many-to-many relation in Java

How can you make the efficient many-to-many -relation from fileID to Words and from word to fileIDs without database -tools like Postgres in Java?
I have the following classes.
The relation from fileID to words is cheap, but not the reverse, since I need three for -loops for it.
alt text http://img191.imageshack.us/img191/4077/oliorakenne1.png
My solution is not apparently efficient.
Other options may be to create an extra class that have word as an ID with the ArrayList of fileIDs.
Reply to JacobM's answer
The relevant part of MyFile's constructors is:
/**
* Synopsis of data in wordToWordConutInFile.txt:
* fileID|wordID|wordCount
*
* Synopsis of the data in the file wordToWordID.txt:
* word|wordID
**/
/**
* Getting words by getting first wordIDs from wordToWordCountInFile.txt and then words in wordToWordID.txt.
*/
InputStream in2 = new FileInputStream("/home/dev/wordToWordCountInFile.txt");
BufferedReader fi2 = new BufferedReader(new InputStreamReader(in2));
ArrayList<Integer> wordIDs = new ArrayList<Integer>();
String line = null;
while ((line = fi2.readLine()) != null) {
if ((new Integer(line.split("|")[0]) == currentFileID)) {
wordIDs.add(new Integer(line.split("|")[6]));
}
}
in2.close();
// Getting now the words by wordIDs.
InputStream in3 = new FileInputStream("/home/dev/wordToWordID.txt");
BufferedReader fi3 = new BufferedReader(new InputStreamReader(in3));
line = null;
while ((line = fi3.readLine()) != null) {
for (Integer wordID : wordIDs) {
if (wordID == (new Integer(line.split("|")[1]))) {
this.words.add(new Word(new String(line.split("|")[0]), fileID));
break;
}
}
}
in3.close();
this.words.addAll(words);
The constructor of Word is at the paste.
Wouldn't a more efficient approach be to assign the link from Word to MyFile at the point that you know the Word is in the File? That is to say, how do you build the list of Words in the MyFile object? If you're reading the words in to the MyFile out of, say, a file on the filesystem, than as you read in each word, you assign its MyFile to the current file.
//within MyFile constructor or setter for Words
while (//there's another word to add) {
Word newWord = new Word(//read word from file);
words.add(newWord);
newWord.setMyFile(this);
}
This is akin to the typical way to manage a bidirectional parent-child relationship:
//in Parent
public void addChild(Child child) {
myChildren.add(child);
child.setParent(this);
}
It might help if you show us how you build the MyFile object.
Edited after you added the code that builds the list of Words:
OK, so having seen the code that builds your Words, I don't think setting up the relationship is the source of your inefficiencies. It looks like you are setting up the relationship in exactly the way I suggested (as you add each word, you give that word the fileID of the corresponding file).
It looks like the source of your inefficiencies are that, for each word, you have to match it up with various things that you currently have in a set of files (e.g. WordToWordId). So for every word you have to loop through every line of that file, and find the match. This is certainly inefficient.
The better approach is to have those pairings in memory in a HashMap, initialized at startup. That way, if you have a particular word and need the corresponding ID, or vice versa, you look them up in your HashMap, which is a constant-time operation. Similarly, for each word, you are looping through every file; again, do that loop ONCE, and store the result in a HashMap. Then lookups become constant time.
Both classes should override hashCode and equals. Thus you will decide what is equal.
Then you will create a set in each of your classes.
public class MyFile implements Comparable<MyFile> {
//your fields here
Set<Word> words = new HashSet<Word>(0);
//Remember to override hashCode and equals
}
public class Word implements Comparable<Word> {
//your fields here
Set<MyFile> words = new HashSet<MyFile>(0);
//Remember to override hashCode and equals
}
In your sets now you will have all the MyFiles.words and otherway around, all the Words.myFile
I think you want that the file know it's words and the words know the files where it is used.
public class File {
private List<Word> words;
public File(){
words=new Vector<Word>();
}
/**
*The method add word to word list.
**/
public addWord(Word word){
this.words.add(word);
word.addFile(this);
}
}
public class Word{
List<File> files;
public addFile(File file){
this.files.add(file);
}
}
or vice versa... but you should question GRASP Design pattern.Maybe your data type is wrong (I dont say wrong because itis your desing,so i respect).

Categories