Hey everybody i'm new to java and I'm doing a bonus assignment for my intro to java class and i was wondering if some one could help guide me for the bonus questions: i just need a starting point! Thanks for any help!
This is the original Requirements for the assignment :
1) A constructor that accepts a single argument, a String for the name of the input file to process. DONE
2) A function named processFile(), that accepts no arguments, and throws an IOException. This function must read the input file's contents and count the number of times each token (word) exists in the file. A member variable HashMap is a good class to use for this.
3) A getFileName() function, no arguments, returns a String that contains the input file name.
4) A getTokenCount() function, no arguments, returns an int that is the total number of tokens (words) in the input file.
5) A getTokenCount() function, that accepts a String argument, and returns the number of times that token (word) appears in the input file.
6) A getTokensHavingCount() function that accepts an int argument (the count), and returns an ArrayList of Strings, where those Strings are the tokens that appear exactly "count" times in the input file.
7) A getTokensHavingLength() function that accepts an int argument (the length), and returns an ArrayListof Strings, where those Strings are the tokens in theinput file that have that exact length.
8) A getAverageOfCounts() function, no arguments, returns the average of the token counts.
As this is the code i have so far,
import java.io.*;
public class Assignment4 {
// Your member variables go here
private String filename;
private int wordcount; // ?
private Map<String, Integer> freq = new HashMap<>(); // <Key,Value>
public Assignment4(final String fileName) {
this.filename = fileName;
}
public void processFile() throws IOException {
File file = new File(filename);
BufferedReader reader;
try {
FileReader fileReader = new FileReader(file);
reader = new BufferedReader(fileReader);
file = null;
String text = "";
String line = reader.readLine();
while (line != null) {
text = text + line + " ";
line = reader.readLine();
}
StringTokenizer st = new StringTokenizer(text);
wordcount = st.countTokens();
}
}
public String getFileName() {
return filename;
}
public int getTokenCount() {
return freq.size;
}
public int getTokenCount(final String key) {
return freq.get(key);
}
public ArrayList<String> getTokensHavingCount(final int count) {
ArrayList<String> wordCount = new ArrayList<String>();
Set<String> set = freq.keySet();
for (String word : set) {
int noOfTimes = freq.get(word);
if (noOfTimes == count)
freq.add(word);
}
return wordCount;
}
public ArrayList<String> getTokensHavingLength(final int length) {
ArrayList<String> wordlength = new ArrayList<String>();
Set<String> set = freq.keySet();
for (String word : set) {
if (word.length() == length)
wordlength.add(word);
}
return wordlength;
}
public int getCountOfTokensHavingCount(final int count) {
return getTokensHavingCount(count).size();
}
public int getCountOfTokensHavingLength(final int length) {
return getTokenHavingLength(count).size;
}
public double getAverageOfCounts() {
ArrayList<String> wordlength = new ArrayList<String>();
double sum = 0.0d;
Set<String> set = freq.keySet();
for (String word : set) {
sum += freq.get(word);
}
return sum / (double) freq.size();
}
}
Bonus #1: Add a function named getCountOfTokensHavingCount(), that accepts an int argument (count), and returns the number of tokens which appear in the input file exactly "count" times.
Bonus #2: Add a function named getCountOfTokensHavingLength(), that accepts an int argument (length), and returns the number of tokens which appear in the input file having exactly "length" characters in the token.
Ok, a few things.
Your function processFile doesn't do what it should do. Your task is to count how often each word appears in the text. Idea: Read the file word by word (take a look at java.util.Scanner); if the word isn't already in your HashMap you add the word as the Key and the number 1 as the value; if the word is already in your HashMap you increase the value by one.
Why do you set file = null in processFile? You should properly close the BufferedReader instead by using a finally. Java can actually do that for you automatically: try(FileReader freader = new FileReader(file); BufferedReader breader = new BufferedReader(freader)) { // Your actual code }.
Your getTokenCount function should return freq.size() (you call a function, not an attribute!).
Also please use always curly braces after an if or a loop, regardless of there is only one thing you do or a huge code block.
Related
We have an assignment/project where we create a parking lot with several different objects then typically each week we add/improve on it. This week we were given a .txt file with lines that look like this "Bicycle%4%2%ABC40%false" or "Auto%22%7%ABC21%false". Each % is used as a delimiter denoting a separate attribute (speed, passenger capacity, serial number, and boolean lock status for bikes) for the respective object (car or bicycle).
We need to read through the file and create a new object in an array with that line using split. What I'm having trouble with is taking the number which is currently a string, parsing it as an int or boolean, then adding that to the new Bicycle (or Auto). Just can't seem to get the syntax right.
Also wondering if my "if" logic is right for if it says Bicycle to start creating a bicycle?
Update:
I think I have the parsing issue figured out, but now it's saying that it can't find my attributes for bicycle... saying "Cannot find symbol" So close!
Here's my code:
public class Driver
{
private static Object myBicycle;
private static Object myAuto;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException
{
Scanner scan = new Scanner(new File("Vehicles.txt"));
ArrayList<Object> myVehicles = new ArrayList<Object>();
while (scan.hasNext())
{
String line = scan.nextLine();
String [] data = line.split("%");
if (data[0].equals("Bicycle"))
{
speed = (Integer.parseInt(data[1]));
PassCap = (Integer.parseInt(data[2]));
serialNumber = (Integer.parseInt(data[3]));
locked = (Boolean.parseBoolean(data[4]));
brand = Brand.randomBrand();
Bicycle myBicycle = new Bicycle(speed, PassCap, serialNumber, locked, brand);
myVehicles.add(myBicycle);
}
I'm not sure what your implementation is, but you could try something like this:
public static void main(String[] args) throws FileNotFoundException
{
Scanner scan = new Scanner(new File("/home/buddha/MYDRIVE/exploring/java/src/Vehicles.txt"));
ArrayList<String> myVehicles = new ArrayList<String>();
while(scan.hasNext()) {
String line = scan.nextLine();
String[] data = line.split("%");
if (data[0].toLowerCase().equals("bicycle")) {
System.out.println(Integer.parseInt(data[1]));
System.out.println(Integer.parseInt(data[2]));
System.out.println(data[3]);
System.out.println(Boolean.parseBoolean(data[4]));
}
else if (data[0].toLowerCase().equals("auto")) {
System.out.println(Integer.parseInt(data[1]));
System.out.println(Integer.parseInt(data[2]));
System.out.println(data[3]);
System.out.println(Boolean.parseBoolean(data[4]));
}
}
}
and just like the setter functions, you can create getter functions and check if the values have been correctly stored.
So, this line:
String [] data = line.split("%");
...takes strings like this:
"Bicycle%4%2%ABC40%false" or "Auto%22%7%ABC21%false"
and turns them into arrays of strings like this:
data[0] : `Bicycle` or `Auto`
data[1] : `4` or `22`
data[2] : `2` or `7`
data[3] : `ABC40` or `ABC21`
data[4] : `false` or `false`
So now you just need to parse those strings into their int and bool equivalents:
speed = Integer.parseInt(data[1]);
passCap = Integer.parseInt(data[2]);
serialNumber = data[3]; // This is a string, right?
locked = Boolean.parseBoolean(data[4]);
If serialNumber is a numeric, then you probably only want the numeric part at the end (e.g. "21" vs "ABC21"):
serialNumber = Integer.parseInt(data[3].Substring(3));
So normally, I know one would use a standard for loop to iterate though the array, like such:
public static void readCodesFromFile(String filename, String[] codes) throws FileNotFoundException {
try ( Scanner fin = new Scanner(new File(filename) ); ) {
for (int i = 0; i <= codes.length - 1; i++) {
codes[i] = fin.nextLine();
}
}
}
But, I desperately want to discover how to do this with a for each loop instead.
At this point I just need to know if it can be done, but also would love the efficiency and cleanliness of using this loop for this task. I have tried something like this, and moved things around many times, but cannot seem to get anything to read properly.
Below is the for each ( : ) I have been working with:
public static void readCodesFromFile(String filename, String [] codes) throws FileNotFoundException {
try (Scanner fin = new Scanner(new File(filename) ); ) {
for (String code : codes) {
codes = fin.nextLine();
}
}
}
At this point I just need to know if it can be done...
No, not as it's written. For one, the spec doesn't allow for it but you're also dealing with immutable Strings. Say, from your second example, code is a reference to an element in your array. Once I do code = "foo";, code now references the (presumably) new String and the array element retains its original value.
But, I desperately want to discover how to do this with a for each
loop instead.
If that's the case, why not invert the problem? Instead of iterating over the array, provide a way to iterate over the file.
In this answer I'm going to assume two things:
You'll provide an Iterable FileReader
You'll use an ArrayList instead of a normal array (this is to get past the indexing issue with the additional benefit that you'll no longer need to know or care about the number of lines in the file)
Here's the FileReader (with a lot not implemented):
class FileReader implements Iterable<String> {
#Override
public Iterator<String> iterator() {
return new FileReaderIterator();
}
#Override
public void forEach(Consumer<? super String> action) { }
#Override
public Spliterator<String> spliterator() { return null; }
class FileReaderIterator implements Iterator<String> {
#Override
public boolean hasNext() {
return false;
}
#Override
public String next() {
return null;
}
#Override
public void remove() { }
#Override
public void forEachRemaining(Consumer<? super String> action) { }
}
}
Assuming you had this implemented you could have used it like so:
List<String> lines = new ArrayList<>();
FileReader reader = new FileReader(...);
for (String line : reader) {
lines.add(line);
}
I'm not suggesting you change your design rather to consider what a different design choice could have provided.
Another way you could achieve this with a basic array very easily would be to encapsulate the line in a class. For example:
class FileLine {
private String line;
public FileLine() {...}
public FileLine(String line) {
this.line = line;
}
public setLine(String line) {
this.line = line;
}
}
Make an array of those, iterate over it with the enhanced for loop, and instead of setting the value of the array string element, set the value of the string member of the FileLine instance. Like so:
// Given an array of instantiated FileLines...
for (FileLine fileLine : fileLines) {
fileLine.setLine(...);
}
Less effort and you don't have to worry about trying to iterate over a file.
I have a set of data that look like this.
1:2:3:4:5
6:7:8:9:10
I have manage to use array list to store the information using a delimiter of ":".
However i would like to store the information of their line numbers together in the array list.
class test
{
String items;
String linenumber;
}
Example:
test(1,1)
test(2,1)
test(6,2)
test(7,2)
Here is my current code.
Scanner fileScanner = new Scanner(new File(fname));
fileScanner.useDelimiter("\n");
int counter = 0; String scounter;
String test;
String events;
while(fileScanner.hasNext())
{
events = fileScanner.next();
scounter = Integer.toString(counter);
Base obj = new Base(scounter, events);
baseArrayList.add(obj);
}
fileScanner.close();
I have try using delimiter "\n" and then trying to split out the string and it is not very successful.
Any advice would be appreciated.
public void Base_Seperator()
{
String temp, temp2;
String[] split;
String days, events;
for(int i = 0; i < baseArrayList.size(); i++)
{
temp = baseArrayList.get(i).events;
temp2 = baseArrayList.get(i).days;
split = temp.split(":");
}
}
Despite the code in #Alex's answer that may solve your problem, your attempt is almost close to get what you want/need. Now you only need to create Test instances and store them in a container, usually a List. I'll add the necessary code to start this from your code:
//it is better to return the List instead of declaring it as a static field
public List<Test> Base_Seperator() {
//try to declare variables in the narrower scope
//String temp, temp2;
//String[] split;
//String days, events;
//this variable must be recognized in all the paths of this method
List<Test> testList = new ArrayList<Test>();
for(int i = 0; i < baseArrayList.size(); i++) {
//these variables should only work within the for statement
String temp = baseArrayList.get(i).events;
String temp2 = baseArrayList.get(i).days;
String[] split = temp.split(":");
//you have splitted the String by :
//now you have every element between : as an item stored in split array
//go through each one and create a new Test instance
//first, let's create the lineNumber variable as String
String lineNumber = Integer.toString(i+1);
//using enhanced for to go through these elements
for (String value : split) {
//now, let's create Test instance
Test test = new Test(value, lineNumber);
//store the instance in testList
testList.add(test);
}
}
//now just return the list with the desired values
return testList;
}
Not part of your question, but some advices:
There are plenty other ways to write code to achieve the same solution (take #Alex's answer as an example). I didn't posted any of them because looks like you're in learning phase, so it will be better for you to first achieve what you're looking for with your own effort (and a little of help).
Not sure if you're doing it (or not) but you should not use raw types. This is, you should always provide a generic type when the class/interface needs it. For example, it is better to define a variable as ArrayList<MyClass> myClassList rather than ArrayList myClass so the class become parameterized and the compiler can help you to avoid problems at runtime.
It is better to always program oriented to interfaces/abstract classes. This means, it is better to declare the variables as an interface or abstract class rather than the specific class implementation. This is the case for ArrayList and List:
List<String> stringList = new ArrayList<String>();
//above is better than
ArrayList<String> stringList2 = new ArrayList<String>();
In case you need to use a different implementation of the interface/abstract class, you will have to change the object initialization only (hopefully).
More info:
What is a raw type and why shouldn't we use it?
What does it mean to "program to an interface"?
Looks like you want to store days instead of lineNumber in your Test instances:
//comment this line
//Test test = new Test(value, lineNumber);
//use this one instead
Test test = new Test(value, days);
First of all you don't need to keep line number info in the test object because it can be inferred from the ArrayList that holds them. If you must though, it should be changed to an int. So,
class test
{
ArrayList items<Integer>;
int linenumber;
public test(int line, String[] input){
items=new ArrayList();
linenumber=line;
//populate with the line read by the Scanner
for(int i=0; i<input.lenth; i++)
items.add(Integer.parseInt(input[i]));
}
}
I use an ArrayList inside test because you don't know how many elements you'll be handling. Moving on to the scanner
Scanner fileScanner = new Scanner(new File(fname));
// fileScanner.useDelimiter("\n"); You don't need this!
String tmp[];
int line=0; //number of lines
while(fileScanner.hasNext()) {
line++;
//this returns the entire line, that's why you don't need useDelimeter()
//it also splits it on '.' I'm not sure if that needs to be escaped but
//just to be sure
tmp=fileScanner.nextLine() . split(Pattern.quote("."));
baseArrayList.add(new test(line, tmp));
}
fileScanner.close();
Here I use test to store the objects you read, I'm not sure what Base is supposed to be.
A Java Bean/construct is required that will hold the day and the item together. The following code will read the text file. Each line will be converted to a List where finally the application will populate the List DayItems collection properly.
public class DayItem {
private int day;
private String item;
public int getDay() {
return day;
}
public void setDay(final int day) {
this.day = day;
}
public String getItem() {
return item;
}
public void setItem(final String item) {
this.item = item;
}
}
And main code
public class ReadFile {
private static final List<DayItem> dayItems = new ArrayList<DayItem>();
public static void main(String args[]) throws FileNotFoundException{
final BufferedReader bufferReader = new BufferedReader(new FileReader("items.txt"));
int lineNumber=0;
try
{
String currentLine;
while ((currentLine = bufferReader.readLine()) != null) {
lineNumber++;
List<String> todaysItems = Arrays.asList(currentLine.split(":"));
addItems(todaysItems,lineNumber);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void addItems(final List<String> todaysItems,final int day){
int listSize = todaysItems.size();
for(int i=0;i<listSize;i++){
String item = todaysItems.get(i);
DayItem dayItem = new DayItem();
dayItem.setDay(day);
dayItem.setItem(item);
dayItems.add(dayItem);
}
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
Ok, so I have an assignment where we must create a java program which asks the user a contacts' name and and a variable amount of the numbers and number types(work, voip..) associated with the contact. The toString() method is suppose to print the contacts name and associated numbers and number types.
Am I passing my Array correctly from my main method to the phoneBookEntry constructor correctly? ( I know there are compile errors, etc, but I want to make sure I am passing the Arrays correctly. Also, is my approach correct?
Suppose to follow UML table accordingly here:
Phone book entry
name : String
phoneNumbers : String[]
phoneTypes : String[]
PhoneBookEntry()
PhoneBookEntry(nam : String) :
PhoneBookEntry(nam : String, numbers : String[], types : String[]) :
getName() : String
setName(nam : String) : void
getPhoneNumber(type : String) : String
setNumbers(numbers : String[], types : String[]) : void
toString() : String
Thanks!
Here is what I have so far:
package phonebookentry;
import java.awt.List;
import java.util.*;
public class PhoneBookEntry
{
private String name;
private String[] phoneNumbers,phoneTypes;
/**
* #param args
*/
public PhoneBookEntry()
{
}
public PhoneBookEntry(String nam, String[]numbers, String[]types)
{
phoneNumbers = numbers;
name = nam;
phoneTypes = types;
toString();
}
public String getName()
{
return name;
}
public void setName(String nam)
{
}
public String[] getPhoneNumber(String type)
{
return phoneTypes;
}
public void setNumbers(String[] numbers, String[] types)
{
this.phoneNumbers = numbers;
this.phoneTypes = types;
}
public String toString()
{
for (int index = 0; index < phoneNumbers.length; index ++ )
return System.out.println(nam, this.phoneNumbers, this.phoneTypes) ;
}
public static void main(String[] args)
{
String phoneN = "0";
ArrayList<String> Ptypes = new ArrayList<String>();
ArrayList<String> Pnumbers = new ArrayList<String>();
while (!phoneN.equals("-1"))
{
String phoneT;
Scanner input = new Scanner(System.in);
// Create an ArrayList to hold some names.
System.out.println("Phone number of Contact: (Input -1, to end)");
phoneN = input.nextLine();
if (phoneN.equals("-1"))
break;
Pnumbers.add(phoneN);
System.out.print("Type of phone number(mobile,home,VOIP,work,etc..):");
phoneT = input.nextLine();
Ptypes.add(phoneT);
}
String nam = "fas";
String[] types = Ptypes.toArray(new String[Ptypes.size()]);
String[] numbers = Pnumbers.toArray(new String[Pnumbers.size()]);
PhoneBookEntry passPhone = new PhoneBookEntry(nam,numbers,types);
passPhone.setNumbers(numbers,
types);
}
}
for (int index = 0; index < phoneNumbers.length; index ++ )
return System.out.println(index) ;
That returns nothing . println() returns void . Again , you are returning at the first iteration of the loop . You should construct a String and return it after the loop. Your public String toString() should return a String to avoid the compilation error.
Something like this :
public String toString()
{
StringBuilder str = new StringBuilder();
for (int index = 0; index < phoneNumbers.length; index ++ )
str.append(...) ; // append whatever you want to display
return str.toString();
}
The toString() method should concatenate out all the phone numbers(I presume)
#Override
public String toString() {
StringBuilder phoneBook = new StringBuilder();
//Generate comma separated entries of phone book
for (int i = 0; i < phoneNumbers.length && i < phoneTypes.length; i++ ) {
if (i > 0) {
phoneBook.append(',');
}
phoneBook = phoneBook.append(phoneNumbers[i])
.append(':')
.append(phoneTypes[i])
}
return phoneBook.toString();
}
Other comments
There is no point calling the toString() method in the constructor.
You should also check whether the lentgh of phoneTypes and phoneNumbers are equal in the constructor.
An empty constructor should be an empty phoneBook. By default the private fields are null. So the toString() method might blow up.
Separate get/set methods for phone numbers/types along with constructors are a bad choice. Instead keep a List where phone numbers could be added/deleted/updated. I guess that is the next assignment. Good Luck !
I am doing a Spell Check project. I have a words list and then the Gettysburg address with some words misspelled. my job is to identify which words are misspelled and then print out astericks or something under the misspelled word when i print out the Address. my issue is in the binarySearch part. Im not sure of the syntax and the javadoc looks like its in chinese. here is my souce code (binarySearch is towards the bottom)
/*
* Assignment 1: Spell Check
* Professor Subrina Thompson
* CS102
*/
package spellcheck;
import java.util.*;
import java.io.*;
public class SpellCheck {
//48,219 words in the words.txt
//Declare Variables
static FileReader reader;
static Scanner input;
static ArrayList <String> wordList = new ArrayList<String>();
static FileReader reader2;
static Scanner input2;
static String testWord;
static String index;
//Main Method
public static void main(String[] args) throws FileNotFoundException {
fileSort();
}
//Open file to be read from
public static void openFile() throws FileNotFoundException {
reader = new FileReader("words.txt");
input = new Scanner(reader);
}
//sort the file
public static void fileSort() throws FileNotFoundException{
openFile();
//read the word list into an ArrayList
while (input.hasNext()){
wordList.add(input.next());
}
//Sort the array
Collections.sort(wordList);
}
//read the gettysburg address
public static void gAddress()throws FileNotFoundException{
reader2 = new FileReader("gettysburg.txt");
input2 = new Scanner(reader2);
//create loop to place word from file into a var then test to see if it is in the dictionary
for(int i = 0; i < wordList.size(); i++){
//place the word into a variable
testWord = input2.next();
//test if the word is in the dictionary
index = Collections.binarySearch(wordList,testWord);
}
}
//compare the address and array through binary search
//print out if spelling is correct
}
PS. I know its not complete and with a lot of loose ends, its still a work-in-progress.
EDIT:
i tried making a new search function based off how i understand binarySearch works. this is the code for that function. the "string w" would be the dictionary word to test against the testWord from the Address:
public static int binarySearch(String w){
int start = 0;
int stop = wordList.size() - 1;
while (start != stop){
int half = ((stop - start)/2) + start;
int res = wordList.get(half).compareToIgnoreCase(w);
if( res == 0 ){
return half;
}
else if( stop - start <= 1 ){
return -1;
}
else if( res > 0 ){
start = half;
}
else if( res < 0 ){
stop = half;
}
}
return -1;
}
This is all you need:
if(index < 0) {
System.out.println(testWord + " not in dictionary");
}
In addition by examining the absolute value of index you can easily find words in dictionary that were alphabetically close to your mistyped word.
The javadoc looks like chinese cause the lists are Generic.
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
Should be read with T as any generic type, T is the type of the key.
The first parameter, the list, must be a list of a type that implements the Comparable interface for a type that T derives from.
In your case, T, the key type, is String. And it's a list of Strings. String implements Comparable, and String is a super class of String. So that is valid.
If you fill in String, the method signature turns into something more normal:
public static int binarySearch(List<String> list, String key)
So therefore, given
int index;
List<String> list;
String key;
an invocation looks like
index = Collections.binarySearch(list, key);
after which index will contain the index of the search key in the list, or a negative number if the key was not found. More precisely:
index of the search key, if it is contained in the list; otherwise,
(-(insertion point) - 1). The insertion point is defined as the point
at which the key would be inserted into the list: the index of the
first element greater than the key, or list.size(), if all elements in
the list are less than the specified key. Note that this guarantees
that the return value will be >= 0 if and only if the key is found.
create loop to place word from file into a var then test to see if it is in the dictionary
But that is not what you are doing. You are creating a loop to go through all the words in the dictionary and checking if the next word in the address is in dictionary and doing nothing about it, whether it is found or not.
If the dictionary has more words then address you will probably get exception, if the address has more words then you will not check all of them.