Method to get an array of inputs in Java - java

I have to do an assignment for school that is basically a small online shop with 10 items.
The way I've done it is with having 2 premade arrays that include the price, and product names. Then I made an array for storing user inputs and an array for storing the multiplied result of input by price. The program works, however the problem is we needed to have a separate file that will contain the item and price list and then call it by using a separate method.
I've been trying to figure out a way to do it but it's a bit above my head to be honest and I'm running out of time. If anyone can advise me how I could separate my functions and product/price lists using methods it would be much appreciated.
This is my program
import java.util.Scanner;
public class dunnes{
public static void main(String args[]){
Scanner in = new Scanner(System.in);
String product[]={"Coat", "Jeans", "Shirt", "Shoes", "Skirt", "Dress", "Socks","Scarf", "Handbag","Vest"};
double price[]={99.99, 53.59, 9.99, 29.99, 24.99, 83.16, 5.99, 10.95, 23.99, 18.99};
int howMany[]=new int[10];
double multiplied[]=new double[10];
int i =0;
boolean err = false;
boolean flag = true;
for(i = 0; i<price.length; i++){
System.out.print(+i+1+ " Please enter how many ");
System.out.print(product[i]+ " you would like to buy (");
System.out.print(price[i]+ ") euro each \n");
do{
err = false;
try{
howMany[i] = Integer.parseInt(in.next());
}catch (Exception e){
err = true;
System.out.print("Incorrect input. Must be whole numbers. \n");
System.out.print(+i+1+ " Please enter how many ");
System.out.print(product[i]+ " you would like to buy (");
System.out.print(price[i]+ ") euro each \n");
}
}while(err);
}
for(i = 0; i<price.length; i++){
multiplied[i]=howMany[i]*price[i];
multiplied[i] = Math.round(multiplied[i] * 100.0) / 100.0;
}
System.out.print("\nUnsorted total bill:\n\n");
for(i = 0; i<price.length; i++){
System.out.print(product[i]+"\t\t");
System.out.print(""+multiplied[i]+"\n");}
while(flag){
flag=false;
for(i=0;i<multiplied.length-1;i++){
if(multiplied[i]>multiplied[i+1]){
double temp = multiplied[i];
multiplied[i] = multiplied[i+1];
multiplied[i+1]= temp;
String temp2=product[i];
product[i]=product[i+1];
product[i+1]=temp2;
flag = true;
}
}
}
System.out.print("\nSorted total bill:\n\n");
for(i = 0; i<price.length; i++){
System.out.print(product[i]+"\t\t");
System.out.print(""+multiplied[i]+"\n");
}
}
}

So, first instead of using multiple arrays of primitives, use one java.util.List of Java objects. You can have a Java class called Product with the fields name and price and getters and setters and then create one Product instance for each of your products and put them in the list. It's doesn't seems like much now, but you'll see this will make making changes to your code much more easier. Like this:
public class Product {
private String name;
private Integer price;
public Product(String name, Integer price) {
this.name = name;
this.price = price;
}
public String getName() {return name;}
public Integer getPrice() {return price;}
public void setName(String name) {this.name = name;}
public void setPrice(Integer price) {this.price = price;}
}
Now on the big part, as I understand you have to load the product list from a file, it's suggest using a properties files to do that, it's a file with on each line a key, the equals sign and a value, and there is already utilities on Java to parse those files, java.util.Properties. There are not exactly designed for this kind of job, but if you are short on time and you don't know how to create a parser yourself, this might be your best solution. You can do something like:
Properties prop = new Properties();
try (InputStream stream = new FileInputStream("path/filename")) {
prop.load(stream);
} finally {
stream.close();
}
List<Product> products = new ArrayList<>();
for(Object key : prop.keySet()) {
String name = (String) key;
Integer price = Integer.valueOf((String) prop.getProperty(key));
products.add(new Product(name, price));
}

Related

Creating multiple objects of the same type with user input?

I'm trying to make a program with three class files, two Objects files and one Main that accesses both and runs operations. The first object file creates objects with one parameter, and then assigns attributes to itself based on said parameter, for example.
public class People {
private int height, weight;
private String specificPerson;
public People(String person){
this.specificPerson = person;
this.height = person.length * 12;
this.weight = person.length * 40;
}
public int getHeight(){return height;}
public int getWeight() {return weight;}
}
These objects are then stored within the array of another object which has a capacity and an array:
public class peopleIndexer {
private int pcapacity, size;
private String[] peopleArray;
public peopleIndexer(int capacity){
this.pcapacity = capacity;
this.peopleArray = new String [capacity];
}
public int getCapacity(){
return pcapacity;
}
public int[] getInfo(String person){
int[] getInfo = new int[2];
int found = Arrays.binarySearch(peopleArray,person);
getInfo[0] = ?.getHeight();
getInfo[1] = ?.getWeight();//I dont know the object name yet so I put "?" for I am not sure
System.out.println("Person" + person + "is " + getInfo[0] + "tall and " + getInfo[1] + " pounds.");
}
}
What I need to know is how to allow the user to make multiple people in the list with input that I can then allow them to retrieve later, for example:
String user_input;
People user_input = new People("user_input");
So that if the users input were to be jack, ryan, and nick, I would have three objects placed in the peopleIndexer as such:
People jack = new People(jack);
People ryan = new People(ryan);
People nick = new People(nick);
Your People constructor takes only one argument and creates a People object..You do not have setters for some of your private variables in the peopleIndexer class, so best to have your main method as part of the peopleIndexer class.
Your "length" attribute in the People constructor is not initialized or declared anywhere, so let's assume it's not there. You must change your "private String[] peopleArray;" to be "private People[] peopleArray;" in order to have people in the array.
public static void main(String args[]){
Scanner input = new Scanner(System.in);
int capacity;
int peopleCount = 0; //used to keep track of people we have in our array
String person = "";
// get the capacity from the user
System.out.println("Enter the number of people you want to capture: ");
capacity = Integer.parseInt(input.nextLine());
//create peopleIndexer object using the given capacity
peopleIndexer pIndexer = new peopleIndexer(capacity);
while(peopleCount < capacity){
//prompt the user for the "People" name, this is the only attibute we need according to your constructor.
System.out.println("Enter person "+(peopleCount + 1)+" name: ");
person = input.nextLine();
//add a new person into the array
peopleArray[peopleCount] = new People(person);
//increase the number of people captured
peopleCount += 1;
}
}

Adding quantities of Duplicate Strings

I've been tasked with sorting a list of categories. A shopping list, if you will. These categories are inputs from the user, items to be bought. After the string name of the category in question is input (using scanner of course) the user is then able to put in the quantity of that category (an integer), followed by the unit cost of that category(a double).
They are prompted to repeat this until the category they name is "end".
This is all fine and dandy, and I've already written code that takes all of this information and finds and prints out the largest cost item, the largest quantity item, and other info. What I need help with is my duplicate categories. For example, suppose the user puts in "cars" followed by an integer 3, followed by the number 24000.00. They then put in "refigerators" followed by 1, followed by 1300.00. And then the user puts in a duplicate of the first entry, which is "cars" followed by an integer 5, followed by the double 37000.00. How can I get my code revisit older entries, add the new quantity to the old one, and store that value without overriding the old stuff? I also need to find the largest average cost of the items in the list. I am new to HashMap, so I'm struggling with the code: // create an arrayList to store values
// create an arrayList to store values
ArrayList<String> listOne = new ArrayList<String>();
listOne.add("+ 1 item");
listOne.add("+ 1 item");
listOne.add("+ 1 item");
// create list two and store values
ArrayList<String> listTwo = new ArrayList<String>();
listTwo.add("+1 item");
listTwo.add("+1 item");
// put values into map
multiMap.put("some sort of user input detailing the name of the item", listOne);
multiMap.put("some other input detailing the name of the next item", listTwo);
// i need the user to input items until they type "end"
// Get a set of the entries
Set<Entry<String, ArrayList<String>>> setMap = multiMap.entrySet();
// time for an iterator
Iterator<Entry<String, ArrayList<String>>> iteratorMap = setMap.iterator();
System.out.println("\nHashMap with Multiple Values");
// display all the elements
while(iteratorMap.hasNext()) {
Map.Entry<String, ArrayList<String>> entry =
(Map.Entry<String, ArrayList<String>>) iteratorMap.next();
String key = entry.getKey();
List<String> values = entry.getValue();
System.out.println("Key = '" + key + "' has values: " + values);
}
// all that up there gives me this:
HashMap with Multiple Values
Key = 'some other input detailing the name of the next item' has values: [+1 item, +1 item]
Key = 'some sort of user input detailing the name of the item' has values: [+ 1 item, + 1 item, + 1 item]
but I haven't given the user a chance to input the number of items or the cost.... I'm lost.
Try this small bit of sample code, it includes a Main class and two dependency classes, StatsPrinter and ShoppingEntry
package com.company;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
String category;
String quantity;
String value;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
HashMap<String, List<ShoppingEntry>> shoppingList = new HashMap<String, List<ShoppingEntry>>();
while(true) {
System.out.print("Enter the category of your item: ");
category = bufferedReader.readLine();
if("end".equals(category)){
break;
}
System.out.print("Enter the quantity of your item: ");
quantity = bufferedReader.readLine();
System.out.print("Enter the value of your item: ");
value = bufferedReader.readLine();
if (shoppingList.containsKey(category)) {
shoppingList.get(category).add(new ShoppingEntry(Integer.parseInt(quantity), Double.parseDouble(value)));
}else{
shoppingList.put(category, new ArrayList<ShoppingEntry>());
shoppingList.get(category).add(new ShoppingEntry(Integer.parseInt(quantity), Double.parseDouble(value)));
}
}
StatsPrinter.printStatistics(shoppingList);
}
}
and the ShoppingEntry class
package com.company;
public class ShoppingEntry {
private int quantity;
private double price;
public ShoppingEntry(){
quantity = 0;
price = 0;
}
public ShoppingEntry(int quantity, double price){
this.quantity = quantity;
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
and finally the StatsPrinter class, which leverages the data structure of the HashMap of ShoppingEntry's to print the desired statistics
package com.company;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
public class StatsPrinter {
private static DecimalFormat format = new DecimalFormat("#.##");
public static void printStatistics(HashMap<String, List<ShoppingEntry>> shoppingList) {
printNuumberOfItems(shoppingList);
printLargestValue(shoppingList);
printLargestAverage(shoppingList);
}
private static void printNuumberOfItems(HashMap<String, List<ShoppingEntry>> shoppingList) {
System.out.println("There are " + shoppingList.keySet().size() + " items in your Shopping List");
}
private static void printLargestValue(HashMap<String, List<ShoppingEntry>> shoppingList) {
double currentLargestPrice = 0;
String largestPriceCategory = new String();
for(String keyValue : shoppingList.keySet()) {
for(ShoppingEntry entry : shoppingList.get(keyValue)) {
if (entry.getPrice() > currentLargestPrice) {
currentLargestPrice = entry.getPrice();
largestPriceCategory = keyValue;
}
}
}
System.out.println(largestPriceCategory + " has the largest value of: " + format.format(currentLargestPrice));
}
private static void printLargestAverage(HashMap<String, List<ShoppingEntry>> shoppingList) {
double currentLargestAverage = 0;
String largestAverageCategory = new String();
double totalCost = 0;
int numberOfItems = 0;
for(String keyValue : shoppingList.keySet()) {
for(ShoppingEntry entry : shoppingList.get(keyValue)) {
totalCost += entry.getPrice();
numberOfItems += entry.getQuantity();
}
if((totalCost / numberOfItems) > currentLargestAverage) {
currentLargestAverage = totalCost / numberOfItems;
largestAverageCategory = keyValue;
}
}
System.out.println(largestAverageCategory + " has the largest average value of: " + format.format(currentLargestAverage));
}
}
Instead of manipulating three separate values, create a class called Item. Implement the Comparable interface such that two Items are equal if they share a common name. See the Javadoc for Comparable for instructions on defining the interface.
public class Item implements Comparable {
[...]
}
Create a list of items.
List<Item> shoppingList;
When you want to add an item to the list, check if the list already contains it first.
// If it's already in the list, add their quantities together
if (shoppingList.contains(newItem))
shoppingList.get(newItem).quantity += newItem.quantity
// Otherwise, add it to the list
else
shoppingList.add(newItem);

Sorting an array list with a delimiter

I have been stuck on this problem for so long and i have no idea what to do.
Basically i have a text file with people names then student number then prize money like this:
Green%3243%1000
Kevin%7657%400
Frank%345%10000
Bob%5435%5000
Stefan%31231%1000
Javis%4532%100
IronMan%5435%2000
Lamp%534%3000
What i want to be able to do is sort the array based on the last number.
I tried this abomination (Don't bother reading it its garbage):
boolean flag = true;
String temp;
int temp1;
int temp2;
while (flag){
flag = false;
for(int j=0; j < list.size() -1; j++ ){
System.out.println(list.get(j));
Scanner s = new Scanner(list.get(j)).useDelimiter("%");
s.next();
s.next();
temp1 = s.nextInt();
Scanner s2 = new Scanner(list.get(j+1)).useDelimiter("%");
s2.next();
s2.next();
temp2 = s2.nextInt();
if (temp1 < temp2){
temp = list.get(j);
list.add(j, list.get(j+1));
list.add(j+1,temp);
flag = true;
}
}
}
But its just infinitely looping. My though while making it was just patching array lists into a bubble sort.
If anyone has any ideas and is willing to share them it will be greatly appreciated.
Java is an object-oriented language, so I'll just use objects:
Create a Student object with the three values you want to store (and a toString() method to print them separated by "%":
public class Student {
private final String name;
private final int number;
private final int prizeMoney;
public Student(final String name, final int number, final int prizeMoney) {
this.name = name;
this.number = number;
this.prizeMoney = prizeMoney;
}
#Override
public String toString() {
return name+"%"+number+"%"+prizeMoney;
}
public int getPrizeMoney() {
return prizeMoney;
}
}
Read your lines as Student objects, and store them in a List:
final Scanner scan = new Scanner(new File("/path/to/StudentsList"));
final List<Student> students = new ArrayList<Student>();
while (scan.hasNextLine()) {
final Scanner line = new Scanner(scan.nextLine());
line.useDelimiter("%");
students.add(new Student(line.next(), line.nextInt(), line.nextInt()));
line.close();
}
scan.close();
Order the List with a custom Comparator, and print it:
students.sort(new Comparator<Student>() {
#Override
public int compare(final Student s1, final Student s2) {
return s1.getPrizeMoney()-s2.getPrizeMoney();
}
});
for (final Student student: students)
System.out.println(student);
Output:
Javis%4532%100
Kevin%7657%400
Green%3243%1000
Stefan%31231%1000
IronMan%5435%2000
Lamp%534%3000
Bob%5435%5000
Frank%345%10000
Here's something for you to get head started.
Create a map for prize money => line as key/value pair
Read each line in the file, parse it and put key/value pair in the above map
Once your map is ready, convert the keys entry set into the collections like list
Sort the collections, using Collections.sort()
Iterate over the created map, and for each value in the collection get the corresponding value from the map.
Hope this helps you to get the workflow.
Id consider creating a 3d array here 8x8x8 from right to left in the array is row, col, and in so [0][0][1] is block one or kevin [0][1][1] is 7657 [1][1][1] is 400. I like this way because not only does it give each 'item' an array it allows you to keep it organized and easily accessable

Array concept on trying to get the no of lines in the file

I have below code which reads the input from a file using scanner class and sorts the input using comparable interface. This code works fine for a fixed array size but I want to count the no.of lines which are there in the file.
public class ReadItemData {
public static void main(String[] args) throws Exception {
Scanner aScanner = new Scanner(new FileReader(
"src//chapter11//Items.txt"));
double avg = 0;
double sum = 0;
Item[] itemArray = new Item[5];
while (aScanner.hasNext())
{
String code = aScanner.next();
String sku = aScanner.next();
double qty = aScanner.nextDouble();
itemArray[count] = new Item(code, sku, qty);
System.out.println(itemArray[i]);
i++;
}
Arrays.sort(itemArray[i]);
System.out.println();
for (Item it : itemArray)
{
System.out.println(it);
sum += qty;
}
avg = sum / 5;
if(qty <= (avg - 10))
{
System.out.println("Quantity is 10 less than the average quantity");
}
}
}
class Item implements Comparable {
private int qty;
private String sku,code;
public Item(String code, String sku,int qty) {
this.code = code;
this.sku = sku;
this.qty = qty;
}
public String getCode() {
return code;
}
public String getSku() {
return sku;
}
public int getQty() {
return qty;
}
public int compareTo(Object o) {
Item i = (Item) o;
return (this.sku).compareTo(i.sku);
}
}
I tried declaring a int variable count and passed it to the array but I am getting ArrayIndexOutOfBoundsException
int count = 0;
Item[] itemArray = new Item[count];
One more issue I am facing is I am calculating the sum inside the loop,but I am not getting the desired results
My input file
PAP ENT 82
WAR HOT 79
TIM JUT 92
BON BLA 76
BON MAG 45
The sum of the quantity goes to 374,but in my code it's calculated to 225 and I am unable to figure out where I am doing wrong.
Any help is appreciated.
Thanks!!
Instead of adding these into a fixed array add them into a java list. Once you have filled the list up use listClass.size() to retrieve the size of the list.
Here's some implementation:
List<Item> itemList = new List<Item>();
while (aScanner.hasNext())
{
String code = aScanner.next();
String sku = aScanner.next();
double qty = aScanner.nextDouble();
itemList.add(new Item(code, sku, qty));
System.out.println(itemList.get(i));
i++;
}
Now use itemList.size() anywhere to retrieve how many entries. You are implementing arrays wrong btw. When you are getting the array out of bounds error is due to the fact that you are initializing the array with 0 positions.
Your sum is incorrect due to not getting the correct item value:
for (Item it : itemArray)
{
System.out.println(it);
//You must get the iterated item quantity (I assume you don't have setters and
//getters
sum += it.qty;
}

Java: Combine 2 List <String[]>

I have two List of array string. I want to be able to create a New List (newList) by combining the 2 lists. But it must meet these 3 conditions:
1) Copy the contents of store_inventory into newList.
2) Then if the item names in store_inventory & new_acquisitions match, just add the two quantities together and change it in newList.
3) If new_acquisitions has a new item that does not exist in store_inventory, then add it to the newList.
The titles for the CSV list are: Item Name, Quantity, Cost, Price.
The List contains an string[] of item name, quantity, cost and price for each row.
CSVReader from = new CSVReader(new FileReader("/test/new_acquisitions.csv"));
List <String[]> acquisitions = from.readAll();
CSVReader to = new CSVReader(new FileReader("/test/store_inventory.csv"));
List <String[]> inventory = to.readAll();
List <String[]> newList;
Any code to get me started would be great! =]
this is what i have so far...
for (int i = 0; i < acquisitions.size(); i++) {
temp1 = acquisitions.get(i);
for (int j = 1; j < inventory.size(); j++) {
temp2 = inventory.get(j);
if (temp1[0].equals(temp2[0])) {
//if match found... do something?
//break out of loop
}
}
//if new item found... do something?
}
I would start by building the newList as a HashMap or TreeMap instead of a List. This makes it easy to search for the matching record. Furthermore, I would convert the String[] to a custom object (e.g. Record) that contains the name, quantity, cost and price field. This would take care of copying the information. The you could try something like this:
Map<String, Record> newMap = new TreeMap<String, Record>();
for(String[] ss : acquisitions) {
Record rec = Record.parse(ss); // For requirement (1)
newMap.put(rec.getName(), rec);
}
for(String[] ss : inventory) {
Record rec = Record.parse(ss); // For requirement (1)
if(newMap.containsKey(rec.getName())) {
// For requirement (2)
// The mergeWith method can then add quantities together
newMap.get(rec.getName()).mergeWith(rec);
} else {
// For requirement (3)
newMap.put(rec.getName(), rec);
}
}
edit
An extra advantage of having a Record object, is that it can be printed to screen much easier by implementing the toString function.
public class Record implements Comparable<Record> {
public static Record parse(String[] ss) {
// TODO: implement some basic parsing
}
private String name;
private int quantity;
private BigDecimal cost, price;
private Record() {}
public String getName() { return name; }
public int getQuantity() { return quantity; }
public BigDecimal getCost() { return cost; }
public BigDecimal getPrice() { return price; }
public int compareTo(Record other) {
return this.name.compareTo(other.name);
}
public String toString() {
return name;
}
}

Categories