I've tried debugging my program and have found the value of ArrayList<String> fileNames in my private void printFilesIn(String word) to be null. I've read What is a NullPointerException and how do I fix it? and it has been very informative, but I don't understand what I can do to fix the code. It's probably a simple fix in the right place, but I would like to have some help on this.
import edu.duke.*;
import java.util.*;
import java.io.*;
public class WordsInFiles {
private HashMap<String,ArrayList<String>> wordInFilesMap;
public WordsInFiles() {
wordInFilesMap = new HashMap<String,ArrayList<String>>();
}
private void addWordsFromFile(File file) {
FileResource fileResource = new FileResource(file);
String fileName = file.getName();
for (String word : fileResource.words()) {
if (!wordInFilesMap.containsKey(word)) {
ArrayList<String> newList = new ArrayList<String>();
newList.add(fileName);
wordInFilesMap.put(word, newList);
}
else if (wordInFilesMap.containsKey(word)
&& !wordInFilesMap.get(word).contains(fileName)) {
ArrayList<String> currentList = wordInFilesMap.get(word);
currentList.add(fileName);
wordInFilesMap.put(word,currentList);
}
}
}
private void buildWordFileMap() {
wordInFilesMap.clear();
DirectoryResource dirResource = new DirectoryResource();
for (File file : dirResource.selectedFiles()) {
addWordsFromFile(file);
}
}
private int maxNumber() {
//returns the maximum number of files any word appears in, considering
// all words from a group of files.
int highest = 0;
for (String word : wordInFilesMap.keySet()) {
ArrayList<String> currentFileList = wordInFilesMap.get(word);
int currentNum = currentFileList.size();
if (currentNum > highest) {
highest = currentNum;
}
}
return highest;
}
private ArrayList<String> wordsInNumFiles(int number) {
//returns an ArrayList of words that appear in exactly number files
ArrayList<String> wordList = new ArrayList<String>();
for (String word : wordInFilesMap.keySet()) {
ArrayList<String> currentList = wordInFilesMap.get(word);
int currentFileCount = currentList.size();
if (currentFileCount == number) {
wordList.add(word);
}
}
return wordList;
}
private void printFilesIn(String word) {
//prints the names of the files this word appears in, one filename per line
ArrayList<String> fileNames = wordInFilesMap.get(word);
for (int index=0; index < fileNames.size(); index++) { //HERE!!
System.out.println(fileNames.get(index));
}
}
public void tester() {
//call buildWordFileMap to select files and build HashMap of words
buildWordFileMap();
//determine maximum number of files any word is in, considering all words
int fileNum = maxNumber();
System.out.println("Max number files any word is in: "+fileNum);
ArrayList<String> wordsInFiles = wordsInNumFiles(fileNum);
System.out.println("Total words in all files: "+wordsInFiles.size());
wordsInFiles = wordsInNumFiles(4);
System.out.println("Total words in four files: "+wordsInFiles.size());
printFilesIn("laid");//
System.out.println("\n");
printFilesIn("tree");
//System.out.println("\nList of words that appear in most files: "+wordsInFiles);
/**
*for (int index=0; index < wordsInFiles.size(); index++) {
* System.out.println("Files where "+wordsInFiles.get(index)+" appear:");
* printFilesIn(wordsInFiles.get(index));
*}
*
*for (String key : wordInFilesMap.keySet()) {
* System.out.println("\nWord: "+key+"\tAppears in files: "
* +wordInFilesMap.get(key));
*}
*/
}
}
In the code I've marked down the location of the error by stating HERE!!!
This is the input that I use when testing this program:
cats are funny and cute
dogs are silly
love animals cats and dogs
love birds and cats
These can be found as files at http://www.dukelearntoprogram.com/course3/archives/ProgrammingImprovingGladLibsData.zip
Related
I'm having trouble reversing a LinkedList. In other words, I need them sorted in z-a order (in contrast to a-z). I've tried Collections.reverse but is not coming into effect? I have the following:
import java.io.*;
import java.util.*;
public class pa9Driver {
//create two list
//1st List is of type word class
//2nd list is of type Anagram_Family
public static List<Word> words = new LinkedList<Word>();
public static List<AnagramFamily> familyList = new LinkedList<AnagramFamily>();
//a main method for driver class
public static void main(String[] args) {
//call the generate method to read word from the file
generate_WordList();
//sort the word list
Collections.sort(words);
//generate the anagram family for the word
generate_FamilyList();
//sort the anagram family list
Collections.sort(familyList, new anagramFamilyComparator());
//reverse the anagram family list
Collections.reverse(familyList);
topFive();
}//main ends
public static void topFive() {
int i;
for(i = 0; i < 15; i++) {
System.out.print(familyList.get(i).getCanonicalForm1() + ", ");
System.out.print(familyList.get(i).getSize() + ": ");
System.out.println(familyList.get(i));
}
}
//method that read word
public static void generate_WordList() {
File inFile12=new File("words.txt");
Scanner fileRead1=null;
try {
fileRead1 = new Scanner(inFile12);
} catch (Exception exe) {
exe.printStackTrace();
System.exit(0);
}
//until the file has words read the words
while(fileRead1.hasNext()) {
words.add(new Word(fileRead1.next()));
}
}
//generate the anagram and add it to the current family
public static void generate_FamilyList() {
Iterator<Word> readWord1 = words.iterator();
Word previousWord1 = words.get(0);
familyList.add(new AnagramFamily());
int index1 = 0;
while(readWord1.hasNext()) {
Word currentWord1 = readWord1.next();
if(currentWord1.getCanonicalForm1().equals(previousWord1
.getCanonicalForm1())) {
familyList.get(index1).add(currentWord1);
} else {
index1++;
familyList.add(new AnagramFamily());
familyList.get(index1).add(currentWord1);
}
previousWord1 = currentWord1;
}
}
}
For convenience sake, I'll only show the first few lines of code that I have and that is expected.
Currently:
[apers, apres, asper, pares, parse, pears, prase, presa, rapes, reaps, spare, spear]
[alerts, alters, artels, estral, laster, ratels, salter, slater, staler, stelar, talers]
Expected:
[spear, spare, reaps, rapes, presa, prase, pears, parse, pares, asper, apres, apers]
[talers, stelar, staler, slater, salter, ratels, laster, estral, artels, alters, alerts]
Try:
Collections.sort(familyList, Comparator.reverseOrder());
Alternatively, you can do:
Collections.sort(familyList, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
//Print list in reverse order
for(String st : familyList){
System.out.println(st);
}
Seeing your code, it seems AnagramFamily is a kind of List, which you are not sorting.
You need to sort the AnagramFamily (List of String) with a StringComparator for getting your desired output.
I think you can use compareTo for this action no ? compareTo from Comparable
Good evening everyone. I'm working on a piece of homework and I finally have it nearly complete. Currently, the only thing stopping compilation is a breakpoint error at line 42. Eclipse tells me that it is the variable "list" being uninitialized, however, i cant find where or why this is happening.
The program is for a homework assignment in beginning java. It is designed to import a list of names from a text file called names.txt, then be able to sort through them in an interface, and while the menu is yet to be added, I want to get compiled and make sure its working before I go changing things again.
import java.util.*;
import java.io.*;
public class Name {
private String givenName;
private int[] ranks = new int[11];
public static void main( String[] args ) {
List<Name> list = new ArrayList<Name>();
loadFile();
System.out.println( list.get( 0 ).getPop( 0 ) );
}
private static void loadFile() {
Scanner inputStream = null;
String fileName = "names.txt";
try {
inputStream = new Scanner( new File( fileName ) );
}
catch (FileNotFoundException e) {
System.out.println( "Error opening file named: " + fileName );
System.out.println( "Exiting..." );
}
while ( inputStream.hasNextLine() ) {
String line = inputStream.nextLine();
String[] tokens = new String[0];
String givenName = tokens[0];
int[] numList = new int[tokens.length - 1];
for ( int i = 1; i < tokens.length; i++ ) {
numList[i - 1] = Integer.parseInt( tokens[i].trim() );
}
list.add( new Name( givenName, numList ) );
}
}
// here we get the name for the
public Name(String name, int[] popularityRanks) {
givenName = name;
for ( int i = 0; i < 11; i++ ) {
ranks[i] = popularityRanks[i];
}
}
public String getName() {
return givenName;
}
public int getPop( int decade ) {
if ( decade >= 1 && decade <= 11 ) {
return ranks[decade];
}
else {
return -1;
}
}
public String getHistoLine( int decade ) {
String histoLine = ranks[decade] + ": ";
return histoLine;
}
public String getHistogram() {
String histogram = "";
for ( int i = 0; i < 11; i++ ) {
histogram += ranks[i] + ": " + this.getHistoLine( i ) + "\n";
}
return histogram;
}
}
In addition, I used lists to configure the variables, but now i am deeply regretting it as I feel far more comfortable with just multi-dimensional arrays. As this is homework related, I completely understand if no one wants to help me fix this second part and give me some code to change the lists to arrays.
I'm burnt out and just want it to compile at this point. Any pointers on where to go from here?
Your list declaration/initialization is in the main and you are trying to access it from loadFile method.
Just move you List<Name> list = new ArrayList<Name>(); as a class variable(put it right above the main) and your code should compile.
Eg:
public class Name {
private String givenName;
private int[] ranks = new int[11];
static List<Name> list = new ArrayList<Name>();
public static void main( String[] args ) {
loadFile();
......
Your list is not visible to the point your are going to add a Name object. Its better to pass the list as a reference to the loadFile() method, As like follows
loadFile(list); // Method call from the main().
And Load file
private static void loadFile(List list) {
// Your code
}
I've restructured your code fixing the scopes and the object definition. If your individual logic is correct(which I haven't really checked), you should get your desired output).
What you seem to have mixed up is the object and the calling client. The Name private class is a private object which is being instantiated in the main method. Subsequently the public methods of the Name object is being called upon.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Solution {
private static class Name{
private final int items = 11;
private String givenName;
private int[] ranks;
//Constructor
public Name(String name, int[] popularityRanks) {
givenName = name;
ranks = new int[items];
for (int i = 0; i < items; i++) {
ranks[i] = popularityRanks[i];
}
}
public String getName() {
return givenName;
}
public int getPop(int decade) {
if (decade >= 1 && decade <= items) {
return ranks[decade];
} else {
return -1;
}
}
public String getHistoLine(int decade) {
String histoLine = ranks[decade] + ": ";
return histoLine;
}
public String getHistogram() {
String histogram = "";
for (int i = 0; i < 11; i++) {
histogram += ranks[i] + ": " + this.getHistoLine(i) + "\n";
}
return histogram;
}
}
public static void main(String[] args) {
List<Name> list = loadFile();
System.out.println(list.get(0).getPop(0));
}
private static List<Name> loadFile() {
List<Name> list = new ArrayList<>();
Scanner inputStream = null;
String fileName = "names.txt";
try {
inputStream = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
System.out.println("Error opening file named: " + fileName);
System.out.println("Exiting...");
}
while (inputStream.hasNextLine()) {
String line = inputStream.nextLine();
String[] tokens = new String[0];
String givenName = tokens[0];
int[] numList = new int[tokens.length - 1];
for (int i = 1; i < tokens.length; i++) {
numList[i - 1] = Integer.parseInt(tokens[i].trim());
}
list.add(new Name(givenName, numList));
}
return list;
}
}
First of all, ill advise you declare your list outside main,
Second, you want to populate the list before calling getPop.
look where you have:
System.out.println(list.get(0).getPop(0));
At this point list.get(0) returns null since the list hasn't been populated yet...and from your code getPop(0) will return -1, so the line above basically doesn't mean anything at that point.
And as for converting the list to arrays to make it "multidimensional"....
First lists can also be "multidimensional", if u know how to declare them...e.g
List> list = new ArrayList();
is a 2d array list.
Second generic lists like the one above are way flexible and have huge advantages over arrays, for example they can be dynamically modified; you can change their size at runtime unlike arrays.
With that said, if you want to convert a list to an array you need the type of the list and it's size and then it's easy using the toArray() method...like this:
String[] array = list.toArray(new String[list.size()]);
Since this is for a beginners class we have not talked about many of the solutions i read here so i wanted to ask based on my code what can i do.
For each name in the file, (last name followed by a comma, followed by one or more spaces, followed by first name) displays the number of times that the names appears in the file. (i.e. name: count). This list of names must be displayed in the ascending order of the names. All first and last names must be capitalized. Each name must be displayed only once.
******* First Names count*********
Adriana 4
Colette 4
Emmanuel 1
Gerri 1
Gretta 1
Kirsten 2
Marcia 2
Neva 1
Shawanda 1
This is what i have so far...
public static void main(String[] args) throws IOException {
// TODO code application logic here
ArrayList<String> first = new ArrayList<>();
ArrayList<String> last = new ArrayList<>();
getNames(first, last);
//display(first);
//display(last);
capitalize(first, last);
//capitalize(last);
ArrayList<String> allNames = new ArrayList<>();
for (int i = 0; i < first.size(); i++) {
allNames.add(last.get(i) + ", " + first.get(i));
}
ArrayList<String> capNames = new ArrayList<>();
System.out.println("***************All Names************");
//System.out.println(allNames);
//capitalize(allNames);
display(allNames);
}
/**
* #param fn
* #param ln
*
* #throws java.io.IOException
*/
public static void getNames(ArrayList<String> fn,
ArrayList<String> ln) throws IOException {
Scanner kb = new Scanner(System.in);
System.out.print("What is the name input file? ");
String fileName = kb.next();
File inpFile = new File(fileName);
Scanner in = new Scanner(inpFile);
while (in.hasNext()) {
String firstName = in.next();
String lastName = in.next();
fn.add(firstName);
ln.add(lastName);
}
}
public static void capitalize(ArrayList<String> first,
ArrayList<String> last) {
for (int i=0; i<first.size(); i++) {
String capFirst = first.get(i).substring(0,1).toUpperCase()
+ first.get(i).substring(1).toLowerCase();
first.set(i, capFirst);
}
for (int i=0; i<last.size(); i++) {
String capLast = last.get(i).substring(0, 1).toUpperCase() +
last.get(i).substring(1).toLowerCase();
last.set(i, capLast);
}
}
public static void display(ArrayList<String> allNames) {
for (int i = 0; i < allNames.size(); i++) {
System.out.println(allNames.get(i));
}
}
Have a look at my comments in the code. I'd modify your code into doing something like this :)
In your code, the method to read the file is incorrect, because first and last names are on the same line separated by a comma. Therefore we need to read this line and split first and last names into seperate strings. However your later comments state that there is no comma, in that case you'll need to modify getNames() method to cater for this.
I've used a HashMap to store first names and their number of appearances.
import java.util.ArrayList;
import java.io.*;
import java.util.Scanner;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Test {
private ArrayList<String[]> allNames;
public static void main(String[] args) throws IOException {
Test t = new Test();
t.go();
}
public void go() {
try {
this.getNames();
this.printAll();
this.printFirstNamesCount();
}
catch(IOException ioEx) {
System.out.println("Input file error. Info : " + ioEx.getMessage());
}
}
private void getNames() throws IOException {
allNames = new ArrayList<String[]>();
Scanner kb = new Scanner(System.in);
System.out.print("What is the name input file? ");
String fileName = kb.next();
File inpFile = new File(fileName);
Scanner in = new Scanner(inpFile);
while (in.hasNext()) {
//slot the string into a arry (last name, first name)
//use nextLine() or it won't read beyond spaces
String[] tmp = in.nextLine().split(",");
//remove white spaces in the first name
tmp[1] = tmp[1].replaceAll("\\s+","");
//capitalize both first and last names
tmp[0] = capitalize(tmp[0]);
tmp[1] = capitalize(tmp[1]);
allNames.add(tmp);
}
}
private void printAll() {
System.out.println("******* All Names *********");
for(String[] tmp : allNames) {
//array index 1 is they first name and 0 is the last name
System.out.println(tmp[1] + " " + tmp[0]);
}
}
private void printFirstNamesCount() {
HashMap<String, Integer> firstNamesCount = new HashMap<String, Integer>();
for(String[] tmp : allNames) {
//we haven't counted this first name yet
if(firstNamesCount.get(tmp[1]) == null) {
firstNamesCount.put(tmp[1], 1);
}
//we have counted this name, so let's just increment it
else {
firstNamesCount.put(tmp[1], (firstNamesCount.get(tmp[1]) + 1));
}
}
//now let's print the hash map
System.out.println("******* First Names Count *********");
for(Map.Entry<String, Integer> e : firstNamesCount.entrySet()) {
System.out.println(e.getKey() + " - " + e.getValue());
}
}
//capitalize the first letter
private String capitalize(String line) {
return Character.toUpperCase(line.charAt(0)) + line.substring(1);
}
}
And my input file looked like this,
Gunasekara, Achintha
Gun, Achintha
Simpson, Homer
Simpson, Bart
Singclar, James
Silver, Paul
Sil, Paul,
Si, Paul,
Kang, David
And you should get an output that looks like,
Archies-MacBook-Pro:Downloads archieg$ java Test
What is the name input file? test.txt
******* All Names *********
Achintha Gunasekara
Achintha Gun
Homer Simpson
Bart Simpson
James Singclar
Paul Silver
Paul Sil
Paul Si
David Kang
******* First Names Count *********
James - 1
David - 1
Homer - 1
Achintha - 2
Paul - 3
Bart - 1
Archies-MacBook-Pro:Downloads archieg$
i modified your code slightly
i added static class NameInf to carry the information of name "the first name and its count so far "
and added method firstNameCounts that search the first arraylist to find the count of repeated names ^-^
static class NameInf {
String name;
int count = 0;
public NameInf(String name) {
this.name = name;
}
#Override
//overide default equal method so two object are equal if with same
//name even they are not have same refence
public boolean equals(Object obj) {
if (obj instanceof NameInf) {
NameInf casted = (NameInf) obj;
return casted.name.equals(this.name);
} else {
return false;
}
}
}
public static void main(String[] args) throws IOException {
// TODO code application logic here
ArrayList<String> first = new ArrayList<>();
ArrayList<String> last = new ArrayList<>();
getNames(first, last);
//display(first);
//display(last);
capitalize(first, last);
//capitalize(last);
ArrayList<String> allNames = new ArrayList<>();
for (int i = 0; i < first.size(); i++) {
allNames.add(last.get(i) + ", " + first.get(i));
}
//ArrayList<String> capNames = new ArrayList<>(); // used for what?
System.out.println("***************All Names************");
//System.out.println(allNames);
//capitalize(allNames);
display(allNames);
ArrayList<NameInf> fnc= firstNamesCount(first);
for(NameInf ni : fnc){
System.out.println(ni.name + " " + ni.count);
}
}
/**
* #param fn
* #param ln
*
* #throws java.io.IOException
*/
public static void getNames(ArrayList<String> fn,
ArrayList<String> ln) throws IOException {
Scanner kb = new Scanner(System.in);
System.out.print("What is the name input file? ");
String fileName = kb.next();
File inpFile = new File(fileName);
Scanner in = new Scanner(inpFile);
while (in.hasNext()) {
String firstName = in.next();
String lastName = in.next();
fn.add(firstName);
ln.add(lastName);
}
}
public static void capitalize(ArrayList<String> first,
ArrayList<String> last) {
for (int i = 0; i < first.size(); i++) {
String capFirst = first.get(i).substring(0, 1)
.toUpperCase() + first.get(i).substring(1).toLowerCase();
first.set(i, capFirst);
}
for (int i = 0; i < last.size(); i++) {
String capLast = last.get(i).substring(0, 1).toUpperCase()
+ last.get(i).substring(1).toLowerCase();
last.set(i, capLast);
}
}
public static void display(ArrayList<String> allNames) {
for (int i = 0; i < allNames.size(); i++) {
System.out.println(allNames.get(i));
}
}
public static ArrayList<NameInf> firstNamesCount(ArrayList<String> firstNames) {
ArrayList<NameInf> temp = new ArrayList<>();
for (String n : firstNames) {
NameInf nameinf = new NameInf(n);
int index = temp.indexOf(nameinf) ;
if (index == -1) {
nameinf.count = 1 ;
temp.add(nameinf);
}else{
temp.get(index).count++;
}
}
return temp ;
}
Okay... So what I've been trying to do is compare two lists: words and d. The words they have in common need to be added to a third list: realWords.
Dictionary is just a list in a different class that has a bunch of words in it.
List<String> realWords = new ArrayList<String>();
Dictionary d = new Dictionary();
These are the things I've tried and haven't worked (and by "worked" I mean the output is nothing, no errors):
Attempt 1
List<String> realWords = new ArrayList<String>(words);
realWords.retainAll(d);
Attempt 2
for(int i = 0; i < words.size(); i++) {
if (d.contains(words.get(i))){
realWords.add(words.get(i));
}
}
Attempt 3
for(String word : words) {
if (d.contains(word)) {
realWords.add(word);
}
}
Attempt 4
for (int i = 0; i < words.size(); i++) {
for (int j = 0; i < d.size(); i++) {
if(words.get(i) == d.get(j)) {
realWords.add(words.get(i));
}
}
}
And then after that portion of code I'm missing:
return realWords;
Thanks in advance!
Edit1: The code for Dictionary.java is:
package a1;
import java.util.*;
public class Dictionary extends ArrayList<String> {
public Dictionary() {
this.add("abalone");
this.add("abandon");
this.add("abashed");
this.add("abashes");
this.add("abasing");
this.add("abating");
this.add("abdomen");
this.add("abducts");
this.add("abetted");
this.add("abetter");
this.add("abettor");
this.add("abiding");
this.add("ability");
this.add("abjured");
this.add("abjures");
this.add("abolish");
this.add("aborted");
this.add("abounds");
this.add("abraded");
// and then more words
}
}
NOTE: This code was provided to us and cannot be changed.
The following code has the following output: [abalone, abolish]
The problem must be somewhere else. Are you sure that "words" contains valid words? Try outputting it and checking manually.
public class Example {
public static class Dictionary extends ArrayList<String> {
public Dictionary() {
this.add("abalone");
this.add("abandon");
this.add("abashed");
this.add("abashes");
this.add("abasing");
this.add("abating");
this.add("abdomen");
this.add("abducts");
this.add("abetted");
this.add("abetter");
this.add("abettor");
this.add("abiding");
this.add("ability");
this.add("abjured");
this.add("abjures");
this.add("abolish");
this.add("aborted");
this.add("abounds");
this.add("abraded");
// and then more words
}
}
public static void main(String[] args) {
List<String> realWords = new ArrayList<String>(
Arrays.asList("abalone", "foobar", "abolish"));
Dictionary d = new Dictionary();
realWords.retainAll(d);
System.out.println(realWords);
}
}
EDIT: Your other attempts are functionally identical, they have the same complexity (O(words.size() * d.size()) but are longer and less obvious/clear.
The code works fine, please debug your code. See the output for reference.
public static void main(String[] args) {
List<String> words = new ArrayList<String>();
words.add("abashes");
words.add("sdqad");
words.add("abducts");
words.add("sadadads");
List<String> realWords = new ArrayList<String>();
Dictionary d = new Dictionary();
for (int i = 0 ; i < words.size() ; i++) {
if (d.contains(words.get(i))) {
realWords.add(words.get(i));
}
}
System.out.println(realWords);
}
output
[abashes, abducts]
Using Java 8 streams I would suggest:
List<Strings> realWords = words.stream()
.filter(d::contains).collect(Collectors.toList());
You can use an enhance for loop
List<String> realWords = new ArrayList<>();
Dictionary d = new Dictionary();
List<String> words = new ArrayList<String>();
words.add("abetted");
words.add("ability");
for (String word : words) {
if (d.contains(word)) {
realWords.add(word);
}
}
System.out.println(realWords);
}
}
I have to write this program for lab. I have to basically illustrate exactly what a hashmap is (keys and values) and the basic operations of declaration, .add(), .get(), and how to get the keys and values from the map. You will then apply this to the frequency histogram problem using the woodchucks.txt input file. I've done all this but I'm stuck on how to write my method that prints the histogram. Can someone please help me out?
import java.io.*;
import java.util.*;
public class Lab8
{
public static void main(String args[]) throws Exception
{
BufferedReader infile = new BufferedReader(new FileReader(args[0]));
HashMap<String,Integer> histogram = new HashMap<String,Integer>();
String word;
while ( (word = infile.ready()) != null )
{
if(histogram.get(word)==null)
histogram.put(word,1);
else
histogram.put(word, histogram.get(word)+1);
}
// YOUR CODE HERE
infile.close();
printHistogram( histogram );
} // END MAIN
// YOU FILL IN THIS METHOD
// READ PROBLEM SPECIFICATION TO SEE WHAT IS THE 80% vs 100% CREDIT SOLUTION
private static void printHistogram( HashMap<String,Integer> hm )
{
// YOU CODE HERE
}
} // END LAB8 CLASS
Would I print the histogram like this?
for ( int i = 0; i < histogram.length; i++ )
{
output += "\n" + i + "\t" + histogram[ i ] + "\t";
for ( int j = 1; j <= histogram[ i ]; j++ )
So if i'll be doing this, i would start from creating two classes, one where i could hold word and number occurrences such as my HistogramItem
public class HistogramItem implements Comparable<HistogramItem> {
#Override
public String toString() {
return "HistogramItem [word=" + word + ", occurence=" + occurence
+ "]";
}
public int getOccurence() {
return occurence;
}
public void updateOccurence() {
this.occurence++;
}
public String getWord() {
return word;
}
public HistogramItem(String word) {
super();
this.word = word;
}
private final String word;
private int occurence = 0;
#Override
public int compareTo(HistogramItem o) {
if (occurence == o.occurence) {
return word.compareTo(o.word);
}
return o.occurence-occurence;
}
}
and other one which will be my actual histogram
public class Histogram {
private Map<String, HistogramItem> map = new HashMap<>();
private List<HistogramItem> list = new ArrayList<>();
public void addWord(String word) {
HistogramItem item = map.get(word);
if (item == null) {
item = new HistogramItem(word);
map.put(word, item);
list.add(item);
}
item.updateOccurence();
}
public List<HistogramItem> getList() {
Collections.sort(list);
return list;
}
}
i'm using two collections, hashmap, because search for entry is much quicker than in list, but list is much easier to sort, list can be created and sorted when requested
How this fits your original excercise? Simple
public static void main(String args[]) throws Exception
{
BufferedReader infile = new BufferedReader(new FileReader(args[0]));
Histogram histogram = new Histogram();
String word;
while ( (word = infile.ready()) != null )
{
histogram.addWord(w);
}
// YOUR CODE HERE
infile.close();
// Below line prints histogram, can be placed in printHistogram method
for (HistogramItem item : histogram.getList()) {
System.out.println(item.toString());
}
} // END MAIN
I figured it out and this is the answer...
import java.io.*;
import java.util.*;
public class Lab8
{
public static void main(String args[]) throws Exception
{
BufferedReader infile = new BufferedReader(new FileReader(args[0]));
HashMap<String,Integer> histogram = new HashMap<String,Integer>();
String word;
while ((infile.ready()))
{
word = infile.readLine();
if(histogram.get(word)== null) //if the word your currently on is not duplicated
{
histogram.put(word,1);
}
else
{
histogram.put(word, histogram.get(word)+1);
}
}
// YOUR CODE HERE
infile.close();
printHistogram( histogram );
} // END MAIN
// YOU FILL IN THIS METHOD
// READ PROBLEM SPECIFICATION TO SEE WHAT IS THE 80% vs 100% CREDIT SOLUTION
private static void printHistogram( HashMap<String,Integer> hm )
{
List <String> keys = new ArrayList<String> (hm.keySet());
Collections.sort(keys);
for (String key: keys)
{
System.out.println(key + "\t" + hm.get(key));
}
}
}// END LAB8 CLASS