0

My code is not working and I have no idea why. This is the error I'm receiving:

Exception in thread "main" java.util.NoSuchElementException
at java.util.AbstractList$Itr.next(AbstractList.java:350)
at java.util.Collections.max(Collections.java:638)
at Project01.getHighestDollarAmount(Project01.java:120)
at Project01.main(Project01.java:45)

I need to take 2 arrayLists (Quantity, Prices) and multiply the values of the 2 and store them in a new arrayList and then find the min and max of that arrayList.

My code:

import java.util.*;
import java.io.*;

public class Project01 {

public static void main(String[] args) {
    ArrayList<String> Titles = new ArrayList<String>();//Declare the array lists that will be used.
    ArrayList<String> Types = new ArrayList<String>();
    ArrayList<Double> Prices = new ArrayList<Double>();
    ArrayList<Integer> Quantities = new ArrayList<Integer>();
    ArrayList<Double> Dollars = new ArrayList<Double>();
    int count = 0;//Set the counter to zero.
    Scanner in = new Scanner(System.in);//Establish the scanner so user input can be properly read.
    String database = getFile(in);//Setting the file name variable from the method below that asks the user for the file's name.
    try {
        File file = new File(database);
        Scanner inputFile = new Scanner(file);
        System.out.println();
        System.out.println("Product Summary Report");
        System.out.println("------------------------------------------------------------");
        while (inputFile.hasNextLine()) {
            getTitle(Titles, inputFile.nextLine());
            getQuantity(Quantities, inputFile.nextInt());
            inputFile.nextLine();
            getPrice(Prices, inputFile.nextDouble());
            inputFile.nextLine();
            getType(Types, inputFile.nextLine());
            System.out.println("Title: " + Titles.get(count));
            System.out.println(" Product Type: " + Types.get(count));
            System.out.println(" Price: " + Prices.get(count));
            System.out.println(" Quantity: " + Quantities.get(count));
            System.out.println();
            count++;
        }
        System.out.println("-----------------------------------------------------------------");
        System.out.println("Total products in database: " + count);
        Integer index = getLargestQuantityTitle(Quantities);
        System.out.println("Largest quantity item : " + Titles.get(index) + " (" + Types.get(index) + ")");
        Double highestTotalDollarAmount = getHighestDollarAmount(Dollars);
        System.out.println("Highest total dollar item: $" + highestTotalDollarAmount);
        Integer index2 = getSmallestQuantityTitle(Quantities);
        System.out.println("Smallest quantity item: " + Titles.get(index2) + " (" + Types.get(index2) + ")");
        System.out.println("Lowest total dollar item: ");
        System.out.println("-----------------------------------------------------------------");
        inputFile.close();
    } catch (IOException e) {
        System.out.println("There was a problem reading from " + database);

    }
    in.close();
}
private static String getFile(Scanner inScanner) {
    System.out.print("Enter database filename: ");
    String fileName = inScanner.nextLine();
    return fileName;
}
private static void getTitle(ArrayList<String> Titles, String title) { //This method is creating the array list of the titles from the input file.
    Titles.add(title);
}
private static void getType(ArrayList<String> Types, String type) { //This method is creating the array list of the types from the input file.
    Types.add(type);
}
private static void getPrice(ArrayList<Double> Prices, double price) { //This method is creating the array list of the prices from the input file.
    Prices.add(price);
}
private static void getQuantity(ArrayList<Integer> Quantities, int quantity) { //This method is creating the array list of the quantities from the input file.
    Quantities.add(quantity);
}
private static Integer getLargestQuantityItem(ArrayList<Integer> Quantities){ //This method is determining the maximum value within the quantities array list.
    return Collections.max(Quantities);
    }
private static Double getHighestPricedItem(ArrayList<Double> prices){ //This method is determining the maximum price within the prices array list.
    return Collections.max(prices);
}
private static Integer getHighestTotalDollarItem(ArrayList<Integer> Prices){ //This method is determining the maximum total value, basically the highest quantity of the item multiplied by it's price.
    return Collections.max(Prices);
}
private static Integer getSmallestQuantityItem(ArrayList<Integer> Quantities){ //This method is determining the minimum value within the quantities array list.
    return Collections.min(Quantities);
    }
private static Integer getLargestQuantityTitle(ArrayList<Integer> Quantities){
    int index = 0;
    Integer largestQuantityMainVariable = getLargestQuantityItem(Quantities);
    for (int i = 0; i < Quantities.size(); i++) {
        if (Quantities.get(i) != null && Quantities.get(i).equals(largestQuantityMainVariable)) {
            index = i;
            break;
        }
    }
    return index;
}
private static Integer getSmallestQuantityTitle(ArrayList<Integer> Quantities){
    int index2 = 0;
    Integer smallestQuantityMainVariable = getSmallestQuantityItem(Quantities);
    for (int i = 0; i < Quantities.size(); i++) {
        if (Quantities.get(i) != null && Quantities.get(i).equals(smallestQuantityMainVariable)) {
            index2 = i;
            break;
        }
    }
    return index2;
}
private static ArrayList<Double> Dollars (ArrayList<Integer> Quantities, ArrayList<Double> Prices){
    int counter=0;
    while (counter<Quantities.size()){
        ArrayList<Double> Dollars = new ArrayList<Double>();
        Dollars.add(Quantities.get(counter)*Prices.get(counter));
    counter++;
    }

    return Dollars(null, null);
}
private static Double getHighestDollarAmount(ArrayList<Double> Dollars){ //This method is determining the maximum price within the prices array list.
    return Collections.max(Dollars);
}

}

My output:

Enter database filename: /Desktop/proj1_input

Product Summary Report
------------------------------------------------------------
Title: The Shawshank Redemption
Product Type: DVD
Price: 19.95
Quantity: 100

Title: The Dark Knight
Product Type: DVD
Price: 19.95
Quantity: 50

Title: Casablanca
Product Type: DVD
Price: 9.95
Quantity: 137

Title: The Girl With The Dragon Tattoo
Product Type: Book
Price: 14.95
Quantity: 150

Title: Vertigo
Product Type: DVD
Price: 9.95
Quantity: 55

Title: A Game of Thrones
Product Type: Book
Price: 8.95
Quantity: 100

-----------------------------------------------------------------
Total products in database: 6
Largest quantity item : The Girl With The Dragon Tattoo (Book)
Exception in thread "main" java.util.NoSuchElementException
at java.util.AbstractList$Itr.next(AbstractList.java:350)
at java.util.Collections.max(Collections.java:638)
at Project01.getHighestDollarAmount(Project01.java:120)
at Project01.main(Project01.java:45)

Input File (.txt file):

The Shawshank Redemption
100
19.95
DVD
The Dark Knight
50
19.95
DVD
Casablanca
137
9.95
DVD
The Girl With The Dragon Tattoo
150
14.95
Book
Vertigo
55
9.95
DVD
A Game of Thrones
100
8.95
Book
Seumas Frew
  • 25
  • 2
  • 9

4 Answers4

3

I see where you have a problem. You are initializing ArrayList in Dollars method on each iteration of while. Change this code

while (counter<Quantities.size()){
        ArrayList<Double> Dollars = new ArrayList<Double>();
        Dollars.add(Quantities.get(counter)*Prices.get(counter));
        counter++;
    }

To this

ArrayList<Double> Dollars = new ArrayList<Double>();

    while (counter<Quantities.size()){
            Dollars.add(Quantities.get(counter)*Prices.get(counter));
        counter++;
        }

so the final method should look like

private static ArrayList<Double> toDollars(ArrayList<Integer> quantities, ArrayList<Double> prices){
int counter=0;
ArrayList<Double> outputInDollars= new ArrayList<Double>();
while (counter<quantities.size()){
    outputInDollars.add(quantities.get(counter)*prices.get(counter));
counter++;
}

return outputInDollars;
}

I also recomend you to use for loop, but it is up to you. Try to name variables using camelcase

shark
  • 995
  • 1
  • 8
  • 19
  • The Dollars Arraylist is empty. I'm not sure how to populate it. I thought I did but apparently not. Can you help? – Seumas Frew Jan 20 '15 at 22:18
  • do you have anything in Quantities arrayList? Your loop depends on Quantities. Debug code and check if while loop is firing. You are also not firing your dollars function. I also modified a body of Dollars function. Compare it to your original version. Your old version will produce exception because you are calling it recursively without stop condition – shark Jan 20 '15 at 22:21
1

I don't see the Dollars method (the one that actually multiplies the Quantities and Prices) being called at all in main. Also, you are instantiating the Dollars Arraylist within the while loop, so you will lose reference to the old data that you added in the list. If that is what you want to do, why even have a counter then?

Having a method named Dollars as well as an attribute with the same name causes a lot of confusion. Please refrain from doing so.

Use List instead of ArrayList for references. Use ArrayList only when you are instantiating the object. Instance attribute names should start with lowercase alphabet or underscore.

Inxsible
  • 700
  • 5
  • 27
0

Collections.max() throws a NoSuchElementException if the collection is empty. And thats ur problem. You dont add any values to the dollars list. Plus you never call Dollars() also update your Dollars function:

private static ArrayList<Double> Dollars (ArrayList<Integer> Quantities, ArrayList<Double> Prices){
    int counter=0;
    // create arrayList outside of the while and return it
    ArrayList<Double> Dollars = new ArrayList<Double>();

    while (counter<Quantities.size()){

        Dollars.add(Quantities.get(counter)*Prices.get(counter));
        counter++;
    }
    // you returned a call to the same function there -> recusive until death
    return Dollars;
}
Wagner Michael
  • 2,172
  • 1
  • 15
  • 29
0

The method causes the exception:

private static Double getHighestDollarAmount(ArrayList<Double> Dollars) {
    return Collections.max(Dollars);
}

because the ArrayList Dollars is empty.

You call that method here:

Double highestTotalDollarAmount = getHighestDollarAmount(Dollars);

The provided list Dollars is empty, because it is not used in this while loop:

while (inputFile.hasNextLine()) {
    getTitle(Titles, inputFile.nextLine());
    getQuantity(Quantities, inputFile.nextInt());
    inputFile.nextLine();
    getPrice(Prices, inputFile.nextDouble());
    inputFile.nextLine();
    getType(Types, inputFile.nextLine());
    System.out.println("Title: " + Titles.get(count));
    System.out.println(" Product Type: " + Types.get(count));
    System.out.println(" Price: " + Prices.get(count));
    System.out.println(" Quantity: " + Quantities.get(count));
    System.out.println();
    count++;
}

So, either you mixed the lists Dollars and Prices and wanted to call:

Double highestTotalDollarAmount = getHighestDollarAmount(Prices);

Or you forgot to "fill" the Dollars list somewhere.

Edit:

I've updated your Dollars method:

 private static List<Double> getTotalPrices(List<Integer> quantities, List<Double> prices){
      List<Double> totalPrices = new ArrayList<>();
      for (int i = 0; i < quantities.size(); i++) {
           totalPrices.add(quantities.get(i) * prices.get(i));
      }
      return totalPrices;
 }

I did following changes:

  1. I've renamed the method to getTotalPrices, because this name is more descriptive than Dollars and it follows the Java Naming Conventions (method names should start with a lowercase letter)
  2. I've changed the types from ArrayList to List, because you should always program to an interface instead of a specific type
  3. I've changed the names of the parameters, due to the Naming Conventions
  4. I've replaced the while loop with a for loop, because these are better in cases like this (iterating over a list)
  5. I've changed the returned value to the new list, instead of a recursive call (which would cause more trouble)
Community
  • 1
  • 1
Tom
  • 16,842
  • 17
  • 45
  • 54