NoSuchElementException and more - java

My assignment is:
Create a file that has 2 columns of numbers: Distance and Speed.
Write a class TravelInfo which has three pieces of information: Speed, Time, Distance.
The class should also have a method calcTime() which calculates the time it will take to reach a destination based on the distance and speed (recall: Time = Distance/Speed)
Write a main program that:
Creates an ArrayList of TravelInfo objects of size 10.
Prompts the user for the name of the file and reads the data into TravelInfo objects
Calls the calcTime() method on each TravelInfo object.
Creates an output file with the data written in the format: Distance, Time, Speed
Every time I run my program I get an error
Exception in thread "main" java.util.NoSuchElementException
Other than this error I think I have done everything right except maybe calling my method, and I still haven't formatted the output file yet (not quite sure how). I can't continue while I get this error.
Here is my main() method:
public static void main(String[] args) throws IOException {
Scanner keyboard = new Scanner(System.in);
ArrayList<TravelInfo> list = new ArrayList<>();
System.out.println("What is the name of the file?");
String filename = keyboard.nextLine();
File f = new File(filename);
Scanner inputFile = new Scanner(f);
while(inputFile.hasNext()) {
int s = inputFile.nextInt();
int d = inputFile.nextInt();
int t = inputFile.nextInt();
TravelInfo p = new TravelInfo(s, d, t);
list.add(p);
TravelInfo cls = new TravelInfo(s,d,t);
cls.calcTime(t);
cls.calcTime(s);
cls.calcTime(d);
// System.out.println("Time is " + cls.calcTime(t));
/*for(int i=0; i<list.size(); i++) {
list.get(i).print();
*/ }
for(TravelInfo k : list)
System.out.println(k);
PrintWriter outputFile = new PrintWriter("Data.txt");
outputFile.println(list);
//outputFile.println();
outputFile.close();
}
}
And my TravelInfo class
public class TravelInfo {
private int speed;
private int distance;
private int time;
public TravelInfo(int s, int d, int t) {
speed = s;
distance = d;
time = t;
}
public int calcTime(int time) {
time = distance/speed;
return time;
}
}

You shall do some more validation, and never use the nextXXX() methods blindly - something like
while(true)
{
if (!inputFile.hasNextInt()) {
System.err.println("Reading file failed - invalid format (s)");
break;
}
int s = inputFile.nextInt();
System.out.println("Reading s = " + s);
if (!inputFile.hasNextInt()) {
System.err.println("Reading file failed - invalid format (d)");
break;
}
int d = inputFile.nextInt();
System.out.println("Reading d = " + d);
if (!inputFile.hasNextInt()) {
System.err.println("Reading file failed - invalid format (t)");
break;
}
int t = inputFile.nextInt();
System.out.println("Reading t = " + t);
// Do some stuff
}
This way, you will avoid the NoSuchElementException, and the application will terminate gracefully. You will get the debugging output on the console. It will also print out what exactly has been read from the file.

As Dorian said, you're missing some validation:
while(inputFile.hasNext()) // Tells you there is "at least" 1 more element.
{
int s = inputFile.nextInt(); // Good
int d = inputFile.nextInt(); // Not good if 's' has taken the last element
int t = inputFile.nextInt(); // Same as above
// rest of the code here...
}
I personnally don't like the 'while(true)' stuff, so here is my version.
while(inputFile.hasNextInt()) // I would use 'hasNextInt()' rather than 'hasNext()'
// This will make sure the next data can be cast to an Integer
{
Integer d = null;
Integer t = null;
Integer s = inputFile.nextInt();
if( inputFile.hasNextInt() {
d = inputFile.nextInt();
if( inputFile.hasNextInt() {
t = inputFile.nextInt();
}
}
// 's' will never be null.
if( d != null && t != null ) {
TravelInfo p = new TravelInfo(s, d, t);
list.add(p);
TravelInfo cls = new TravelInfo(s,d,t);
cls.calcTime(t);
cls.calcTime(s);
cls.calcTime(d);
// System.out.println("Time is " + cls.calcTime(t));
/*for(int i=0; i<list.size(); i++)
{
list.get(i).print();
*/ }
for(TravelInfo k : list)
System.out.println(k);
PrintWriter outputFile = new PrintWriter("Data.txt");
outputFile.println(list);
//outputFile.println();
outputFile.close();
}
else if( inputFile.hasNext()) {
// At this point, you there the remaining data cannot be safely cast to an Integer.
}
else {
// Not enough data to process.
}
}
public class TravelInfo {
private int speed;
private int distance;
private int time;
public TravelInfo(int s, int d, int t) {
speed = s;
distance = d;
time = t;
}
public int calcTime(int time) {
time = distance/speed;
return time;
}
// Override toString() instead of using the default Object.toString()
#Override
public String toString() {
// Return whatever 'String' you want
return String.format( "%d, %d, %d", speed, distance, time );
}
}

Related

Java: Sort files in a folder in reverse semantic order

I have a set of pdf files that I'm supposed to sort in reverse semantic order. The files are:
Release_Notes_CNV_22.3.pdf
Release_Notes_CNV_22.9.pdf
Release_Notes_CNV_22.12.pdf
Release_Notes_CNV_23.5.pdf
I have the following code to sort them. Unfortunately, the 22.3 file appears after 22.9. Can someone please tell me where I'm going wrong. A little help would be appreciated :D
The order I'm getting is:
Release_Notes_CNV_23.5.pdf
Release_Notes_CNV_22.12.pdf
Release_Notes_CNV_22.3.pdf // 22.3 appearing before 22.9
Release_Notes_CNV_22.9.pdf
The correct order should be:
Release_Notes_CNV_23.5.pdf
Release_Notes_CNV_22.12.pdf
Release_Notes_CNV_22.9.pdf
Release_Notes_CNV_22.3.pdf
My Code:
private String getReleaseNotesPdfFileAbsolutePath(long number) {
File folder = new File(String.format("%s%s%s", appHome, File.separator, releaseNotesFilesHomeFolderName));
File[] fileNames = folder.listFiles();
int i=1;
Arrays.sort(fileNames, new Comparator<File>() {
#Override
public int compare(File o1, File o2) {
float n1 = extractNumber(o1.getName());
float n2 = extractNumber(o2.getName());
int val = (int)n2 - (int)n1;
System.out.println(n2 + " " + (int)n2 + " : " + n1 + " " + (int)n1 + " : " + val);
return val;
}
private float extractNumber(String name) {
float i = 0;
try {
int s = name.lastIndexOf('_')+1;
int e = name.lastIndexOf('.');
String number = name.substring(s, e);
i = Float.parseFloat(number);
} catch(Exception e) {
i = 0; // if filename does not match the format
// then default to 0
}
return i;
}
});
for(File file : fileNames){
if( i == number ) {
return String.format("%s%s%s%s%s", appHome, File.separator, releaseNotesFilesHomeFolderName, File.separator, file.getName());
}
i = i+1;
}
return String.format("%s%s%s%s%s", appHome, File.separator, releaseNotesFilesHomeFolderName, File.separator, Constants.RELEASE_NOTES_PDF);
}
Tried the above code using comparator.
The problem comes from the fact that you compare decimal numbers. In the scope of decimals 0.12 < 0.3, because 0.3 = 0.30. But you want to compare decimal part as an integers, where 12 > 3. To achieve this you need to first compare integer parts, and then decimal parts.
You can represent this as custom class:
class MyDecimal {
private final int integerPart;
private final int decimalPart;
//constructor and getters
}
If you are using java 14 or above, record is even better.
Simplified example:
public class Test {
public static void main(String[] args) {
File[] fileNames = new File[]{new File("Release_Notes_CNV_23.5.pdf"),
new File("Release_Notes_CNV_22.12.pdf"),
new File("Release_Notes_CNV_22.3.pdf"),
new File("Release_Notes_CNV_22.9.pdf")};
Arrays.sort(fileNames, new Comparator<>() {
#Override
public int compare(File o1, File o2) {
MyDecimal n1 = extractNumber(o1.getName());
MyDecimal n2 = extractNumber(o2.getName());
//integer part first in reverse order
int result = Integer.compare(n2.getIntegerPart(), n1.getIntegerPart());
if (result != 0) {
return result;
}
//decimal part second, if integer parts were equal
return Integer.compare(n2.getDecimalPart(), n1.getDecimalPart());
}
private MyDecimal extractNumber(String name) {
try {
int s = name.lastIndexOf('_') + 1;
int e = name.lastIndexOf('.');
String number = name.substring(s, e);
String[] parts = number.split("\\.");
return new MyDecimal(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
} catch (Exception e) {
return new MyDecimal(0, 0);
}
}
});
System.out.println(Arrays.toString(fileNames));
}
}
Prints - [Release_Notes_CNV_23.5.pdf, Release_Notes_CNV_22.12.pdf, Release_Notes_CNV_22.9.pdf, Release_Notes_CNV_22.3.pdf].

Creating triple-ended queue with efficient random access

I have been tasked to solve a question concerning the creation of a triple-ended queue with efficient random access, as outlined in this: https://open.kattis.com/problems/teque. I created a program based around using 2 very large arrays, one containing the front half of all stored integers so far and the other the back half, with both being of the same size or the front half containing at most 1 more element than the back half after every insertion operation. This should allow all insertion and retrieval operations to be of O(1) time complexity, but the code just keeps exceeding the given time limit. Can anyone tell me what is wrong with my code? Here it is:
import java.util.*;
import java.io.*;
public class Teque3 {
static int[] front = new int[1_000_000];
static int[] back = new int[1_000_000];
static int frontHead = 499_999;
static int backHead = 499_999;
static int frontSize = 0;
static int backSize = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
for (int i = 0; i < n; i++) {
String[] line = br.readLine().split(" ");
if (line[0].equals("get")) {
int index = Integer.parseInt(line[1]);
if (index >= frontSize) System.out.println(back[backHead + index - frontSize]);
else System.out.println(front[frontHead + index]);
continue;
}
if (frontSize == backSize) {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
frontSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
front[frontHead + frontSize] = back[backHead];
frontSize++;
backHead++;
} else if (line[0].equals("push_middle")) {
front[frontHead + frontSize] = Integer.parseInt(line[1]);
frontSize++;
}
} else {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
backHead--;
back[backHead] = front[frontHead + frontSize];
backSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
backSize++;
} else if (line[0].equals("push_middle")) {
backHead--;
back[backHead] = Integer.parseInt(line[1]);
backSize++;
}
}
}
}
}
You could try to minimze IO-Operations: Collect your programm output. Instead of writing System.out.println better create a new StringBuilder to collect everything. In the end write all at once.
static StringBuilder result = new StringBuilder();
...
private static void result(int value) {
result.append(value).append("\n");
}
...
if (index >= frontSize) result(back[backHead + index - frontSize]);
else result(front[frontHead + index]);
...
System.out.println(result);
Decouple read from parse and process: Create one thread for reading the operations. But the operations in a Queue. Start another thread for the process.

Search in Hashmap

Using for loop to compare the input value with the hashmap if it matches any value in the hash-map then the code prints all the related values with that time.
The result shows out for me NULL
System.out.println("Please enter time :");
Scanner scan = new Scanner(System.in);
String value = scan.nextLine();//Read input-time
Measurement measurement = measurements.get(value);//there can only be 1 Measurement for 1 time
if(measurement != null){
System.out.println(measurement);
}}
Class Measurement:
public void getTimeInfo(String value)
{
value = Measurements.get(time);
if (value == null) {
throw new MeasurementException();
}
System.out.println("The detailed info : " + this.time + "-" + this.temp+ " "+ this.wind+ "-" + this.humid );
}
}
}
Following the 3 steps (ignoring the Json part) u mentioned and reusing some of your code i can provide u this code:
Main.java:
public class Main {
static HashMap<String, Measurement> measurements = new HashMap();
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {//Create 3 measurements
String time = ""+i;
measurements.put(time, new Measurement(time, (float) i, (float) i, (float) i));
}
System.out.println("Please enter time :");
Scanner scan = new Scanner(System.in);
String value = scan.nextLine();//Read input-time
Measurement measurement = measurements.get(value);//there can only be 1 Measurement for 1 time
if(measurement != null){
System.out.println(measurement);
}
}
}
Measurement.java:
public class Measurement {
String time ;
Float temp;
Float wind;
Float humid;
int iD;
public Measurement(String d, Float t, Float w, Float h){
this.time = d;
this.temp = t;
this.wind = w;
this.humid = h;
}
#Override
public String toString() {
return "The detailed info : " + this.time + "-" + this.temp+ " "+ this.wind+ "-" + this.humid;
}
}
It might not fit exactly your needs but it can be a help.

Finding smallest and largest population and the average

I've been working on getting this program to work. I'm having a little trouble getting the program to read the files I have created, census2000 and census2010. These contain the 50 states and their population in 2000 and 2010. I believe that the rest of my program is correct. I was told to use methods to find the smallest population, largest population and the average. Here is two lines from the 2000 file:
Alabama 4447100
Alaska 626932
Here is my program:
public static void main(String[] args) throws IOException {
String state = "";
int population = 0;
int p = 0, s = 0, pop = 0, stat = 0, populate = 0, sum = 0;
File f = new File("census2000.txt");
Scanner infile = new Scanner(f);
infile.useDelimiter("[\t|,|\n|\r]+");
while (infile.hasNext()) {
checksmall(p, s);
checklargest(pop, stat);
checkAverage(populate, sum);
population = infile.nextInt();
state = infile.next("/t");
System.out.println(state + "has" + population + "people");
}
System.out.println(state + "has smallest population of" + population);
prw.close();
}
public static boolean checksmall(int p, int s) {
boolean returnValue;
if (p < s) {
returnValue = true;
} else {
returnValue = false;
}
return (returnValue);
}
public static boolean checklargest(int pop, int stat) {
boolean returnVal;
if (pop > stat) {
returnVal = true;
} else {
returnVal = false;
}
return (returnVal);
}
public static int checkAverage(int populate, int sum) {
int retVal;
retVal = populate + sum;
return (retVal);
}
}
What am I doing wrong?
I believe the problem is here:
state = infile.next("/t");
I think what you're trying to do is skip a tab in the file and read the state? You could do that by reading in the line and then splitting the line using \t as the delimiter.
String line;
while (infile.hasNextLine()){
line = infile.nextLine();
String data[] = line.split("\\s+");
state = data[0];
population = Integer.parseInt(data[1]);
}
edit: also as the other answer points out, you're attempting to perform functions on the file's data before it's read.
You need to be calling checksmall, checklargest and checkAverage after/while the file is loaded.

Infinite while loop in java, not reading in sentinel

I've had this problem throughout multiple programs, but I can't remember how I fixed it last time. In the second while loop in my body, the second sentinel value is never read in for some reason. I've been trying to fix it for a while now, thought I might see if anyone had any clue.
import java.text.DecimalFormat; // imports the decimal format
public class Car {
// Makes three instance variables.
private String make;
private int year;
private double price;
// Makes the an object that formats doubles.
public static DecimalFormat twoDecPl = new DecimalFormat("$0.00");
// Constructor that assigns the instance variables
// to the values that the user made.
public Car(String carMake,int carYear, double carPrice)
{
make = carMake;
year = carYear;
price = carPrice;
}
// Retrieves variable make.
public String getMake()
{
return make;
}
// Retrieves variable year.
public int getYear()
{
return year;
}
// Retrieves variable price.
public double getPrice()
{
return price;
}
// Checks if two objects are equal.
public boolean equals(Car c1, Car c2)
{
boolean b = false;
if(c1.getMake().equals(c2.getMake()) && c1.getPrice() == c2.getPrice() &&
c1.getYear() == c2.getYear())
{
b = true;
return b;
}
else
{
return b;
}
}
// Turns the object into a readable string.
public String toString()
{
return "Description of car:" +
"\n Make : " + make +
"\n Year : " + year +
"\n Price: " + twoDecPl.format(price);
}
}
import java.util.Scanner; // imports a scanner
public class CarSearch {
public static void main(String[] args)
{
// initializes all variables
Scanner scan = new Scanner(System.in);
final int SIZE_ARR = 30;
Car[] carArr = new Car[SIZE_ARR];
final String SENT = "EndDatabase";
String carMake = "";
int carYear = 0;
double carPrice = 0;
int count = 0;
int pos = 0;
final String SECSENT = "EndSearchKeys";
final boolean DEBUG_SW = true;
// Loop that goes through the first list of values.
// It then stores the values in an array, then uses the
// values to make an object.
while(scan.hasNext())
{
if(scan.hasNext())
{
carMake = scan.next();
}
else
{
System.out.println("ERROR - not a String");
System.exit(0);
}
if(carMake.equals(SENT))
{
break;
}
if(scan.hasNextInt())
{
carYear = scan.nextInt();
}
else
{
System.out.println("ERROR - not an int" + count);
System.exit(0);
}
if(scan.hasNextDouble())
{
carPrice = scan.nextDouble();
}
else
{
System.out.println("ERROR - not a double");
System.exit(0);
}
Car car1 = new Car(carMake, carYear, carPrice);
carArr[count] = car1;
count++;
}
// Calls the method debugSwitch to show the debug information.
debugSwitch(carArr, DEBUG_SW, count);
// Calls the method printData to print the database.
printData(carArr, count);
// Loops through the second group of values and stores them in key.
// Then, it searches for a match in the database.
**while(scan.hasNext())**
{
if(scan.hasNext())
{
carMake = scan.next();
}
else
{
System.out.println("ERROR - not a String");
System.exit(0);
}
if(carMake.equals(SECSENT))
{
break;
}
if(scan.hasNextInt())
{
carYear = scan.nextInt();
}
else
{
System.out.println("ERROR - not an int" + count);
System.exit(0);
}
if(scan.hasNextDouble())
{
carPrice = scan.nextDouble();
}
else
{
System.out.println("ERROR - not a double");
System.exit(0);
}
Car key = new Car(carMake, carYear, carPrice);
// Stores the output of seqSearch in pos.
// If the debug switch is on, then it prints these statements.
if(DEBUG_SW == true)
{
System.out.println("Search, make = " + key.getMake());
System.out.println("Search, year = " + key.getYear());
System.out.println("Search, price = " + key.getPrice());
}
System.out.println("key =");
System.out.println(key);
pos = seqSearch(carArr, count, key);
if(pos != -1)
{
System.out.println("This vehicle was found at index = " + pos);
}
else
{
System.out.println("This vehicle was not found in the database.");
}
}
}
// This method prints the database of cars.
private static void printData(Car[] carArr, int count)
{
for(int i = 0; i < count; i++)
{
System.out.println("Description of car:");
System.out.println(carArr[i]);
}
}
// Searches for a match in the database.
private static int seqSearch(Car[] carArr, int count, Car key)
{
for(int i = 0; i < count; i++)
{
boolean b = key.equals(key, carArr[i]);
if(b == true)
{
return i;
}
}
return -1;
}
// Prints debug statements if DEBUG_SW is set to true.
public static void debugSwitch(Car[] carArr, boolean DEBUG_SW, int count)
{
if(DEBUG_SW == true)
{
for(int i = 0; i < count; i++)
{
System.out.println("DB make = " + carArr[i].getMake());
System.out.println("DB year = " + carArr[i].getYear());
System.out.println("DB price = " + carArr[i].getPrice());
}
}
}
}
I think this is your problem, but I might be wrong:
Inside your while loop, you have these calls:
next()
nextInt()
nextDouble()
The problem is that the last call (nextDouble), will not eat the newline. So to fix this issue, you should add an extra nextLine() call at the end of the two loops.
What happens is that the next time you call next(), it will return the newline, instead of the CarMake-thing.

Categories