I'm having trouble on how to create a new ordered map that reads a file char by char. Here is the beginning of my program
public class Practice {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter the file name to random write: ");
String fileName = keyboard.nextLine();
System.out
.print("Enter nGram length, 1 is like random, 12 is like the book: ");
int nGramLength = keyboard.nextInt();
keyboard.close();
Practice rw = new Practice(fileName, nGramLength);
rw.printRandom(500);
}
private HashMap<String, ArrayList<Character>> all;
private int nGramLength;
private String fileName;
private StringBuilder theText;
private static Random generator;
private String nGram;
public Practice(String fileName, int nGramLength) {
this.fileName = fileName;
this.nGramLength = nGramLength;
generator = new Random();
makeTheText();
setRandomNGram();
setUpMap(); // Algorithm considered during section.
}
private void makeTheText() {
Scanner inFile = null;
try {
inFile = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
theText = new StringBuilder();
while (inFile.hasNextLine()) {
theText = theText.append(inFile.nextLine().trim());
theText = theText.append(' ');
}
}
public void setRandomNGram() {
generator = new Random();
int temp = theText.length() - nGramLength - 1;
int start = generator.nextInt(temp);
nGram = theText.substring(start, start + nGramLength);
}
// Read theText char by char to build a OrderedMaps where
// every possible nGram exists with the list of followers.
// This method need these three instance variables:
// nGramLength theText all
private void setUpMap() {
// TODO: Implement this method
for(int i = 0; i < nGramLength; i++)
{
ArrayList<Character> key = all.get(i);
}
}
// Print chars random characters. Please insert line breaks to make your
// output readable to the poor grader :-)
void printRandom(int howMany) {
// TODO: Implement this method
}
}
I need to work on the last two methods, but I am confused as to how to iterate through a hashmap
You can iterate over a HashMap by iterating over its entrySet(). That will give you both the key and value:
for (Map.Entry<String, ArrayList<Character>> entry : all) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
Alternatively you can iterate only over its keySet() or valueSet(), but it sounds as if you want both key and value here.
The answer is that you do not iterator over a map. Maps do not have an iterator because that would make no sense. What would it iterator over the keys the values or both. The solution is turn your keys or values into a collection. You do this with the values method (returns a collection of the values) and keySet method (returns a set of the keys in the map) You can then call those collection's iterator methods.
Related
I read words from a text file and then create a new Word object for each word and store the objects into an ArrayList. The text of the word is passed into the object as a parameter. I have overridden the equals(Object) and hashCode() method of the word class to check for the equality of objects based on text of a word instead of object memory location. I am trying to store all unique words in ArrayList as unique objects and increment the occurrence of the word object if the word repeats in the text file.
Scanner file = new Scanner(new File(textfile));
ArrayList<Word> words = new ArrayList<Word>();
while (file.hasNext()) {
Word w = new Word(fileWord);
if (words.contains(w)) {
w.increaseCount();
} else {
words.add(w);
}
}
Word Class is;
public class Word {
private String text;
private int count;
public Word(String wordText) {
text = wordText;
}
public void increaseCount() {
count += 1;
}
#Override
public boolean equals(Object wordToCompare) {
if (wordToCompare instanceof Word) {
Word castedWord = (Word) wordToCompare;
if (castedWord.text.equals(this.text)) {
return true;
}
}
return false;
}
#Override
public int hashCode() {
return text.hashCode();
}
}
Unique words get added to the ArrayList, but my count does not increment. How to increment the count
The problem is with this statement in your code;
while (file.hasNext()) {
Word w = new Word(fileWord);
if (words.contains(w)) {
w.increaseCount(); // Here's what goes wrong.
} else {
words.add(w);
}
}
You're invoking the function increaseCount() on newly created object and that would get replaced during the next iteration, and you lost the reference. But the actual object is in the ArrayList and you should increase the value of that object. So, I would say, your code should be changed like this;
Scanner file = new Scanner(new File(textfile));
ArrayList<Word> words = new ArrayList<Word>();
while (file.hasNext()) {
Word w = new Word(fileWord);
if (words.contains(w)) {
words.get(words.indexOf(w)).increaseCount(); // Note the change here.
} else {
w.increaseCount(); // This is for the first occurrence as 'count' is 0 initially.
words.add(w);
}
}
The problem is that you create new instance of Word in the loop.
When the array contains the newly created Word, you increase the count for it, not the existing instance which already added to the array before.
Consider to use Map for the problem, the key is the word and the value is the count.
package example.stackoverflow;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WordCount {
public static void main(String[] args) {
List<String> sourceList = Arrays.asList("ABC", "XYZ", "HGK", "ABC", "PWT", "HGK", "ABC");
Map<String, Integer> wordCount = new HashMap();
for (String word : sourceList) {
if (wordCount.get(word) != null) {
wordCount.put(word, wordCount.get(word) +1);
} else {
wordCount.put(word, 1);
}
}
System.out.println(wordCount);//output: {ABC=3, XYZ=1, PWT=1, HGK=2}
}
}
Check this answer:
Scanner file = new Scanner(new File(textfile));
ArrayList<Word> words = new ArrayList<Word>();
while (file.hasNext()) {
Word w = new Word(fileWord);
if (words.contains(w)) {
w.increaseCount();
int index = words.indexOf(w);
Word w1 = words.get(index);
w1.increaseCount();
words.set(index, w1);
} else {
words.add(w);
}
}
Below are chunks of my code from my quiz program in Java. I am trying to read/write high scores to a file and sort the high score table.
public static void main(String[] args) throws IOException {
sort(highscoreTable);
int score1 = 0;
int score2 = 0;
int totalscore = 0;
int NumberofQuestions = 5;
// RECORDS TO STORE QUESTION, ANSWER WOULD BE HERE //
private static void start(int NumberofQuestions, String[] Answers, String[][] questions, int score1, int score2, int totalscore) throws IOException {
// DISPLAYED ON THE HOME SCREEN SO USER CAN CHOOSE WHAT THEY WANT TO DO
System.out.println("[0] Leave\n");
while(true) {
System.out.println("[1] Play");
System.out.println("[2] Highscore");
System.out.print("Enter Choice: ");
String useranswer = scanner.nextLine();
System.out.println();
if (useranswer.equals("1")) {
mainLoop(NumberofQuestions, Answers, questions, score1, score2, totalscore);
} else if (useranswer.equals("2")) {
sort(highscoreTable);
} else if (useranswer.equals("0")) {
try {
save();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
I wanted this bit to be displayed on the screen first, if the user presses 2, i wanted to program to read from the file and show the preious high scores
public static void save() throws IOException {
String aggFileName = "agg-"+String.valueOf("06.txt");
FileWriter fstream = new FileWriter(aggFileName);
BufferedWriter out = new BufferedWriter(fstream);
for (Map.Entry<String, String> entry : highscoreTable.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); //this statement prints out my keys and values
out.write(entry.getKey() + "--" + entry.getValue() + "\n");
System.out.println("Done");
out.flush(); // Flush the buffer and write all changes to the disk
}
out.close(); // Close the file
}
The save method works perfectly and I have no problem with it.
public static void mainLoop(int NumberofQuestions, String[]Answers, String[][] questions, int score1, int score2, int totalscore) throws IOException {
// USER WOULD ANSWER QUESTIONS HERE
addHighscore(name, totalscore);
}
public static void addHighscore(String name, int totalscore) throws IOException {
highscoreTable.put(String.valueOf(totalscore), name);
}
The function here adds the users name and total score to a treemap
public static void highscoreImport(HashMap highscoreTable) throws IOException {
String filePath = "agg-06.txt";
String line;
BufferedReader reader = new BufferedReader(new FileReader(filePath));
while ((line = reader.readLine()) != null)
{
String[] parts = line.split("--", 2);
if (parts.length >= 2)
{
String key = parts[0];
String value = parts[1];
highscoreTable.put(key, value);
} else {
}
}
for (Object key : highscoreTable.keySet())
{
System.out.println(key + "--" + highscoreTable.get(key));
}
reader.close();
}
This is the part I'm having issues with. I want the program to get the information from the file, and now merge it with the data that is coming from the users recent quiz, and then sort the scores (I want a high score table) so that when the users types "2" to see the high score table, it will be in descending order
public static void sort(HashMap highscoreTable) throws IOException {
System.out.println("Before Sorting:");
Set set = highscoreTable.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
Map<Integer, String> map = new TreeMap<Integer, String>(highscoreTable);
System.out.println("After Sorting:");
Set set2 = map.entrySet();
Iterator iterator2 = set2.iterator();
while(iterator2.hasNext()) {
Map.Entry me2 = (Map.Entry)iterator2.next();
System.out.print(me2.getKey() + ": ");
System.out.println(me2.getValue());
}
}
Here, the list outputted "before" and "after" sorting is the same unsorted list
Sorry for the long read, I would appreciate any help or pointers in fixing this.
Since in the addHighscore method you are doing:
highscoreTable.put(String.valueOf(totalscore), name);
I assume it is a Map<String, String> (both key and value types are String).
But in the sort method you do...
Map<Integer, String> map = new TreeMap<Integer, String>(highscoreTable);
If the types of highscoreTable are correctly defined, the TreeMap instantiation should fail at compiling time. If not, and as the constructor TreeMap(Map) gets ordered by the natural order of its keys (see Javadoc), it is probably ordering it by String order or other. So "111" will be before "12" and other unexpected results. It is a good practice to define the types in all the collections and other generic type classes.
The trouble is with the type of the score. You are inserting the score as a string. A second minor issue is the sort order should be reversed.
Look at the following example:
public class Test {
public static void main(String[] args) throws IOException {
System.out.println("String scores:");
HashMap<String, String> scores = new HashMap<>();
scores.put("12", "John");
scores.put("240", "Mary");
scores.put("14", "Sean");
scores.put("35", "Pat");
sort(scores);
System.out.println();
System.out.println("Integer scores:");
HashMap<Integer,String> integerScores = new HashMap<>();
integerScores.put(12, "John");
integerScores.put(240, "Mary");
integerScores.put(14, "Sean");
integerScores.put(35, "Pat");
sort(integerScores);
}
public static void sort(HashMap highscoreTable) throws IOException {
System.out.println("Before Sorting:");
Set set = highscoreTable.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry me = (Map.Entry)iterator.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
Map<Integer, String> map = new TreeMap<Integer, String>(Collections.reverseOrder()); // Descending
map.putAll(highscoreTable);
System.out.println("After Sorting:");
Set set2 = map.entrySet();
Iterator iterator2 = set2.iterator();
while(iterator2.hasNext()) {
Map.Entry me2 = (Map.Entry)iterator2.next();
System.out.print(me2.getKey() + ": ");
System.out.println(me2.getValue());
}
}
}
This example uses your sort method on 'scores', and 'integerScores'.
Here is the sorted output:
String scores:
35: Pat
240: Mary
14: Sean
12: John
Integer scores:
240: Mary
35: Pat
14: Sean
12: John
You can see in the first sort that 35 comes before 240, because 3 comes before 2. It is doing a string sort. The second sort is by the value of an integer. Once you understand this, it is easy to fix your code.
The original code inserts the key as a String:
highscoreTable.put(key, value);
The key should be an Integer:
highscoreTable.put(Integer.valueOf(key), value);
Also note that the provided answer can be easily run. It includes data (which is simpler that attaching a file), and output. When questions are formatted this way, it is easier to get help.
I read Bert Bates and Katie Sierra's book Java and have a problem.
The Task: to make the game "Battleship" with 3 classes via using ArrayList.
Error: the method setLocationCells(ArrayList < String >) in the type
SimpleDotCom is not applicable for the arguments (int[])
I understand that ArrayList only will hold objects and never primatives. So handing over the list of locations (which are int's) to the ArrayList won't work because they are primatives. But how can I fix it?
Code:
public class SimpleDotComTestDrive {
public static void main(String[] args) {
int numOfGuesses = 0;
GameHelper helper = new GameHelper();
SimpleDotCom theDotCom = new SimpleDotCom();
int randomNum = (int) (Math.random() * 5);
int[] locations = {randomNum, randomNum+1, randomNum+2};
theDotCom.setLocationCells(locations);
boolean isAlive = true;
while(isAlive) {
String guess = helper.getUserInput("Enter the number");
String result = theDotCom.checkYourself(guess);
numOfGuesses++;
if (result.equals("Kill")) {
isAlive = false;
System.out.println("You took " + numOfGuesses + " guesses");
}
}
}
}
public class SimpleDotCom {
private ArrayList<String> locationCells;
public void setLocationCells(ArrayList<String> loc) {
locationCells = loc;
}
public String checkYourself(String stringGuess) {
String result = "Miss";
int index = locationCells.indexOf(stringGuess);
if (index >= 0) {
locationCells.remove(index);
if(locationCells.isEmpty()) {
result = "Kill";
} else {
result = "Hit";
}
}
return result;
}
}
public class GameHelper {
public String getUserInput(String prompt) {
String inputLine = null;
System.out.print(prompt + " ");
try {
BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
inputLine = is.readLine();
if (inputLine.length() == 0)
return null;
} catch (IOException e) {
System.out.println("IOException:" + e);
}
return inputLine;
}
}
convert ArrayList to int[] in Java
Reason for Basic Solution
Here's a simple example of converting ArrayList<String> to int[] in Java. I think it's better to give you an example not specific to your question, so you can observe the concept and learn.
Step by Step
If we have an ArrayList<String> defined below
List<String> numbersInAList = Arrays.asList("1", "2", "-3");
Then the easiest solution for a beginner would be to loop through each list item and add to a new array. This is because the elements of the list are type String, but you need type int.
We start by creating a new array of the same size as the List
int[] numbers = new int[numbersInAList.size()];
We then iterate through the list
for (int ndx = 0; ndx < numbersInAList.size(); ndx++) {
Then inside the loop we start by casting the String to int
int num = Integer.parseInt(numbersInAList.get(ndx));
But there's a problem. We don't always know the String will contain a numeric value. Integer.parseInt throws an exception for this reason, so we need to handle this case. For our example we'll just print a message and skip the value.
try {
int num = Integer.parseInt(numbersInAList.get(ndx));
} catch (NumberFormatException formatException) {
System.out.println("Oops, that's not a number");
}
We want this new num to be placed in an array, so we'll place it inside the array we defined
numbers[ndx] = num;
or combine the last two steps
numbers[ndx] = Integer.parseInt(numbersInAList.get(ndx));
Final Result
If we combine all of the code from "Step by Step", we get the following
List<String> numbersInAList = Arrays.asList("1", "2", "-3");
int[] numbers = new int[numbersInAList.size()];
for (int ndx = 0; ndx < numbersInAList.size(); ndx++) {
try {
numbers[ndx] = Integer.parseInt(numbersInAList.get(ndx));
} catch (NumberFormatException formatException) {
System.out.println("Oops, that's not a number");
}
}
Important Considerations
Note there are more elegant solutions, such as using Java 8 streams. Also, it's typically discouraged to store ints as Strings, but it can happen, such as reading input.
I can't see where you call setLocationCells(ArrayList<String>) in your code, but if the only problem is storing integers into an ArrayList there is a solution:
ArrayList<Integer> myArray = new ArrayList<Integer>();
myArray.add(1);
myArray.add(2);
It is true that you can't use primitive types as generics, but you can use the Java wrapper types (in this case, java.lang.Integer).
I am attempting to output the contents of an ArrayList, but no matter which approach I try I seem get the location of the Array rather than the contents of the Array. Running each of the following together gives me:
run:
[[Ljava.lang.String;#55f96302, [Ljava.lang.String;#232204a1, [Ljava.lang.String;#4554617c, [Ljava.lang.String;#7f31245a, [Ljava.lang.String;#2503dbd3, [Ljava.lang.String;#5cad8086]
[Ljava.lang.String;#232204a1
[Ljava.lang.String;#232204a1
[Ljava.lang.String;#232204a1
Here's the code snippet:
// Each of the following approaches results in
// [Ljava.lang.String;#232204a1
// instead of the actual value of the ArrayList.
String test = accountNumbers.get(1);
System.out.println(test);
System.out.println(accountNumbers.get(1));
System.out.println(accountNumbers.get(1).toString());
// This actually outputs:
// [[Ljava.lang.String;#55f96302, [Ljava.lang.String;#232204a1, [Ljava.lang.String;#4554617c, [Ljava.lang.String;#7f31245a, [Ljava.lang.String;#2503dbd3, [Ljava.lang.String;#5cad8086]
String str = Arrays.toString(accountNumbers.toArray());
System.out.println(str);
I'm not really sure what's causing this. Is there some way to get the contents to display?
EDIT: Here's the entire method. An answer on another question (here) advised me to try using ArrayList instead of the approach I was using. I adapted the suggestion, but I felt that the problems were better placed in a new question rather than as an edit to that question.
protected static void loadAccountInformationFromFile() throws Exception
{
Scanner account = new Scanner(new File(INPUT_ACCOUNT_FILE)).useDelimiter(",");
int sortCount = 1;
List<String> accountNumbers = new ArrayList<>();
List<String> firstNames = new ArrayList<>();
List<String> lastNames = new ArrayList<>();
List<String> balances = new ArrayList<>();
List<String> lastVariables = new ArrayList<>();
do {
String[] temp1 = account.next().split(",");
String temp2 = "" + temp1;
if (sortCount == ACCOUNT_NUMBER_COUNT) {
accountNumbers.add(temp2);
} else if (sortCount == FIRST_NAME_COUNT) {
firstNames.add(temp2);
} else if (sortCount == LAST_NAME_COUNT) {
lastNames.add(temp2);
} else if (sortCount == BALANCE_COUNT) {
balances.add(temp2);
} else if (sortCount == LAST_VARIABLE_COUNT) {
lastVariables.add(temp2);
}
if (sortCount < MAX_VALUES_PER_LINE) {
sortCount++;
} else {
sortCount = 1;
}
} while (account.hasNext());
// Each of the following approaches results in
// [Ljava.lang.String;#232204a1
// instead of the actual value of the ArrayList.
String test = accountNumbers.get(1);
System.out.println(test);
System.out.println(accountNumbers.get(1));
System.out.println(accountNumbers.get(1).toString());
// This actually outputs:
// [[Ljava.lang.String;#55f96302, [Ljava.lang.String;#232204a1, [Ljava.lang.String;#4554617c, [Ljava.lang.String;#7f31245a, [Ljava.lang.String;#2503dbd3, [Ljava.lang.String;#5cad8086]
String str = Arrays.toString(accountNumbers.toArray());
System.out.println(str);
account.close();
// I want to adapt what I previously used to access the ArrayLists.
// Bank bank = new Bank();
//
// bank.openAccount(new CheckingAccount(10100, new Customer("Adam", "Apple"),500.00,false));
// bank.openAccount(new CheckingAccount(10101, new Customer("Beatrice", "Bagel"),2000.00,true));
// bank.openAccount(new SavingsAccount(2010, new Customer("Adam", "Apple"),5000.00,0.02));
}
EDIT 2: Here are the class variables:
private final static String INPUT_ACCOUNT_FILE = "accountInfo.txt";
private static final int ACCOUNT_NUMBER_COUNT = 0;
private static final int FIRST_NAME_COUNT = 1;
private static final int LAST_NAME_COUNT = 2;
private static final int BALANCE_COUNT = 3;
private static final int LAST_VARIABLE_COUNT = 4;
private final static int MAX_VALUES_PER_LINE = 5;
EDIT 3: For the benefit of those who may read this question late and be confused by some of the comments on the correct answer, part of my issue was related to an issue with the text file itself. This is an example of the formatting of the text file:
10100,First,Last,Balance,value
10101,First,Last,Balance,value
20100,First,Last,Balance,value
Also: To get the ArrayLists to store the correct strings I had to change sortCount from:
int sortCount = 1;
to
int sortCount = 0;
Because when it was set at 1 it would store the first name in the account number string.
The problem is not in your "displaying" but in the way you read the contents from the file.
Your code prints out correctly "addresses" because the strings in accountNumbers instance are really these values (because you put array of strings into one single string). So what really happens is that in your temp2 String is your temp1.toString().
You are using wrong delimiter (you should use default one for whitespaces instead):
Scanner account = new Scanner(new File(INPUT_ACCOUNT_FILE));
And then assign values like:
if (temp1.length > ACCOUNT_NUMBER_COUNT) {
accountNumbers.add(temp1[ACCOUNT_NUMBER_COUNT]);
if (temp1.length > FIRST_NAME_COUNT) {
firstNames.add(temp1[FIRST_NAME_COUNT]);
if (temp1.length > LAST_NAME_COUNT) {
lastNames.add(temp1[LAST_NAME_COUNT]);
if (temp1.length > BALANCE_COUNT) {
balances.add(temp1[BALANCE_COUNT]);
if (temp1.length > LAST_VARIABLE_COUNT) {
lastVariables.add(temp1[LAST_VARIABLE_COUNT]);
}
Your temp2 and sort variables are not needed.
Anyway it is a bit weird to use these collections. I would rather suggest to do it like:
Scanner scanner = new Scanner(new File(INPUT_ACCOUNT_FILE));
Collection<Account> bank = new ArrayList<>();
while (scanner.hasNext()) {
String[] fields = scanner.next().split(",");
if (fields.length < MAX_VALUES_PER_LINE) {
continue; // incomplete row, skip it or maybe throw some exception?
}
String number = fields[ACCOUNT_NUMBER_COUNT];
Customer customer = new Customer(fields[FIRST_NAME_COUNT], fields[LAST_NAME_COUNT]);
double balance = Double.valueOf(fields[BALANCE_COUNT]);
String type = fields[LAST_VARIABLE_COUNT];
Account a = null;
switch (type) {
case "N": {
a = new CheckingAccount(number, customer, balance);
break;
}
case "0.02": {
a = new SavingsAccount(number, customer, balance);
break;
}
default: {
continue; // unknown type of account, skip it or maybe throw some exception?
}
}
bank.add(a);
}
String temp2 = "" + temp1;
You are trying to concat a blank with a string array, this is equals with
String temp2 = "" + temp1.toString();
Note that toString() of Array will return object references, not the value.
So you should try to convert array to some Java Collection class that implements the toString() method like ArrayList
String temp2 = "" + Arrays.asList(temp1).toString();
or you can also do
String temp2 = "" + Arrays.toString(temp1);
Both will give you the String value (and some "[" and "]" too, I guess, because of the toString() implementation of ArrayList and Arrays, you can work it out).
I have a file with the following:
5
212:Float On:Modest Mouse
259:Cherub Rock:Smashing Pumpkins
512:Won't Get Fooled Again:The Who
417:Teen Age Riot:Sonic Youth
299:PDA:Interpol
I need to create a array but I need to take into account the integer it starts with, then read the rest as strings taking into account the initial line containing only an integer. I've made the method to read the file and print, just don't know how to split it up.
An example of how to do it:
String s = "212:Float On:Modest Mouse"; // your input - a line from the file
String[] arr = s.split(":");
System.out.println(arr[0]); // your int
// The rest of the array elements will be the remaining text.
// You can concatenate them back into one string if necessary.
you can read file using Scanner
readlines = new Scanner(filename);
while(readlines.hasNextLine())
{
String line = readlines.nextLine();
String[] values = line.split(":");
int firstColumn = -1;
if (values.length > 0) {
try {
firstColumn = Integer.parseInt(values[0]);
} catch (NumberFormatException ex) {
// the value in the first column is not an integer
}
}
}
I've grown a habit of reading the entire file into a List, then handling the List in memory. Doing this is not the only option.
Once I have the file read in, I look at the first line to know how many tracks to expect in the remaining file. I then would loop through the remaining List to either get the number of tracks from the first line or until I reach the end of the list, in the event that the number of tracks (from the first line) exceeds the actual amount of tracks that are in the file.
As I go through the tracks I would use substring to break the line apart, and convert just the first part.
Update
Base on your comment, I've updated to use split instead of substring. Then some basic alignment formatting for output
public static void main(String[] args) throws Exception {
String yourFile = "path to your file.txt";
List<String> yourFileLines = new ArrayList<>(Files.readAllLines(Paths.get(yourFile)));
// You know the first line is suppose to be the number of tracks so convert it to a number
int numberOfTracks = Integer.valueOf(yourFileLines.get(0));
// Either go to the number of tracks or till the end of file
List<Track> tracks = new ArrayList<>();
for (int i = 1; (i <= numberOfTracks && i < yourFileLines.size()); i++) {
String currentFileLine = yourFileLines.get(i);
String[] currentFileLinePieces = currentFileLine.split(":");
Track currentTrack = new Track();
currentTrack.TrackTime = Integer.valueOf(currentFileLinePieces[0]);
currentTrack.TrackTitle = currentFileLinePieces[1];
currentTrack.TrackArtist = currentFileLinePieces[2];
tracks.add(currentTrack);
}
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "TITLE", "ARTIST", "TIME"));
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "-----", "------", "----"));
for (Track currentTrack : tracks) {
System.out.println(currentTrack);
}
}
public static class Track {
public int TrackTime;
public String TrackTitle;
public String TrackArtist;
#Override
public String toString() {
return String.format("%-20s\t\t%-20s\t\t%-20d", TrackTitle, TrackArtist, TrackTime);
}
}
Results:
Here's an example using a Scanner, and breaking everything into methods. You should be able to use List and ArrayList. Results are the same.
public static void main(String[] args) throws Exception {
String yourFile = "data.txt";
List<String> yourFileLines = readFile(yourFile);
if (yourFileLines.size() > 0) {
// You know the first line is suppose to be the number of tracks so convert it to a number
int numberOfTracks = Integer.valueOf(yourFileLines.get(0));
List<Track> tracks = getTracks(numberOfTracks, yourFileLines);
printTracks(tracks);
}
}
public static List<String> readFile(String pathToYourFile) {
List<String> yourFileLines = new ArrayList();
try {
File yourFile = new File(pathToYourFile);
Scanner inputFile = new Scanner(yourFile);
while(inputFile.hasNext()) {
yourFileLines.add(inputFile.nextLine().trim());
}
} catch (Exception e) {
System.out.println(e);
}
return yourFileLines;
}
public static List<Track> getTracks(int numberOfTracks, List<String> yourFileLines) {
List<Track> tracks = new ArrayList();
// Either go to the number of tracks or till the end of file
for (int i = 1; (i <= numberOfTracks && i < yourFileLines.size()); i++) {
String currentFileLine = yourFileLines.get(i);
String[] currentFileLinePieces = currentFileLine.split(":");
Track currentTrack = new Track();
currentTrack.TrackTime = Integer.valueOf(currentFileLinePieces[0]);
currentTrack.TrackTitle = currentFileLinePieces[1];
currentTrack.TrackArtist = currentFileLinePieces[2];
tracks.add(currentTrack);
}
return tracks;
}
public static void printTracks(List<Track> tracks) {
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "TITLE", "ARTIST", "TIME"));
System.out.println(String.format("%-20s\t\t%-20s\t\t%-20s", "-----", "------", "----"));
for (Track currentTrack : tracks) {
System.out.println(currentTrack);
}
}
public static class Track {
public int TrackTime;
public String TrackTitle;
public String TrackArtist;
#Override
public String toString() {
return String.format("%-20s\t\t%-20s\t\t%-20d", TrackTitle, TrackArtist, TrackTime);
}
}