How to retrieve previous values from HashMap? - java

I have the following code where I'm reading from a text file. The text file i as follows:
111 Laptop 500 10
222 Mobile 120 8
333 Notebook 4 100
444 Chocolates 3 50
555 Guitar 199 5
666 LenovoLaptop 470 10
777 HPLaptop 450 10
888 SonyVAIO 525 5
If the user enters ID as 111, the following should be the output:
111 Laptop 500 10
666 LenovoLaptop 470 10
777 HPLaptop 450 10
888 SonyVAIO 525 5
I'm storing the the contents of the text file in a HashMap. Here is the code:
public void comparableItems(String ID)
{
File f = new File("C://Class/items.txt");
HashMap<String, Item> map = new HashMap<String, Item>();
try
{
Scanner scan = new Scanner(f);
while(scan.hasNext())
{
String line = scan.nextLine();
String temp[] = line.split(" ");
Item it = new Item(temp[0], temp[1], Double.parseDouble(temp[2]), Integer.parseInt(temp[3]));
map.put(it.itemID, it);
}
if(map.containsKey(ID))
{
Item item = map.get(ID);
if(item.price>=item.price+100 && item.price<=item.price-100)
{
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
Here is the Item class:
public class Item
{
String itemID;
String itemName;
double price;
int quantity;
public Item(String itemID, String itemName, double price, int quantity)
{
this.itemID = itemID;
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
public void printItemDetails()
{
System.out.println("ID\tItemName\tUnitPrice\tQuantity");
System.out.println("===================================================");
System.out.println(this.itemID+ "\t" +this.itemName+ "\t" +this.price+ "\t"+this.quantity);
}
}
How do I get the desired output? I'm in the learning stages of Java Collections. So please bear with me.
Can someone help me here?
Thanks!

Your Map isn't doing you much good. Since you know what reference item ID you're looking for before you even parse the file, you could just capture that item when (and if) you see it during the parse. You do need some kind of collection to hold all the other items, but a List would be a better choice for this particular task.
In any case, the thrust of your question seems to be about examining all the other items you parse from the file. For this, you want to iterate over the Map's values() view (and to get your comparisons right):
for (Item otherItem : map.values()) {
if((otherItem.price <= item.price + 100)
&& (otherItem.price >= item.price - 100)) {
otherItem.printItemDetails();
}
}
If you collected the items in a List instead of a Map, then you would replace map.values() in the above with just list (or whatever name you use for the List).

For what you say you want (items with prices near the desired item), a HashMap isn't an efficient datastore.
However, since it sounds like this is your homework, once you use map.get("111") to get your laptop, get the price P, and then iterate over the hashmap to get any item whose price is within your desired delta of P. The Collections tutorial tells you how to iterate over a collection.

Related

How to calculate some specific data function from the data of a large CSV file

I'm trying to work out the most expensive county to rent a building from data in a CSV file. The data from each column I need the data from has been put into a list. The price range is set by the user so the outer most for loop and if statement ensure that the buildings considered are in the set price range.
The price of a building is also slightly complicated because the price is the minimum stay x price.
In the code below I am trying to get the average property value of one county just son I can get the basic structure right before I carry on, but I'm kind of lost at this point any help would be much appreciated.
public int sampleMethod()
{
ArrayList<String> county = new ArrayList<String>();
ArrayList<Integer> costOfBuildings = new ArrayList<Integer>();
ArrayList<Integer> minimumStay = new ArrayList<Integer>();
ArrayList<Integer> minimumBuildingCost = new ArrayList<Integer>();
try{
//Code to read data from the CSV and put the data in the lists.
}
}
catch(IOException | URISyntaxException e){
//Some code.
}
int count = 0;
int avgCountyPrice = 0;
int countyCount = 0;
for (int cost : costOfBuildings) {
if (costOfBuildings.get(count) >= controller.getMin() && costOfBuildings.get(count) <= controller.getMax()) {
for (String currentCounty: county) {
for (int currentMinimumStay: minimumStay) {
if (currentCounty.equals("sample county")) {
countyCount++;
int temp = nightsPermitted * cost;
avgCountyPrice = avgCountyPrice + temp / countyCount;
}
}
}
}
count++;
}
return avgCountyPrice ;
}
Here is a sample table to depict what the CSV looks like, also the CSV file has more than 50,000 rows.
name
county
price
minStay
Morgan
lydney
135
5
John
sedury
34
1
Patrick
newport
9901
7
Let’s describe the algorithm of your task: Group the CSV file by county, calculate the average price in each group, and find the country that has the highest average price for buildings. The code will be rather long if you try to finish the task using Java. It is convenient and simple to get this done in SPL, the open-source Java package. The language only needs one line of code:
A
1
=file("data.csv").import#ct().groups(county;avg(price):price_avg).top(-1;price_avg).county
 
SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as mostExpensiveCounty.splx and invoke it in Java in the same way you call a stored procedure:
…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st = con.prepareCall("call mostExpensiveCounty()");
st.execute();
…

Splitting a loop into the same equal parts each time

I have created an app that recieves orders and i want to be able to cycle 4 sets of orders so each device can choose what set of orders it sees. I want to split the orders by the order_id so
a: 1 5 9 13 ect
b: 2 6 10 14 ect
c: 3 7 11 15 ect
d: 4 8 12 16 ect
I recieve the orders through a loop but can change to a list of array lists if nessecary. I have tried a couple ways to get the result im after but have had no luck. Thank you in advance
EDIT (Rough idea of what i want)
//Data from Json
for (int i = 0; i < jArray.length(); i++) {
try {
JSONObject oneObject = jArray.getJSONObject(i);
// Pulling items from the array
final int objectsItem = oneObject.getInt("order_id");
if(checkboxA == checked)
{
//Show orders 1,5,9,13 ect
}
if(checkboxB == checked)
{
//Show orders 2,6,10,14 ect
}
if(checkboxA == checked)
{
//Show orders 3,7,11,15 ect
}
if(checkboxA == checked)
{
//Show orders 4,8,12,16 ect
}
}
`
This way i can show all orders, all parts of orders, so the orders can be equally split between many devices without interacting with each other - Hope this makes more sense
What about using a Map? You can set every order_id as the key for an entry and all orders as the value of the entry (for example List of orders).
For example:
Map<Character, List<Integer>> map;
Than you can get a certain order_id with:
List<Integer> orders = map.getValue('a');
for (Integer order : orders) {
//do logic here
}

Scanner and String Comparison

I have the following text in a file :
3
apple 4 1.00
chicken 1 3.25
cookie 38 0.25
avocado 1 4.00
blueberries 1 5.00
chicken 2 3.25
milk 9 4.50
tomato 27 0.50
chicken 2 3.25
I want to list each item and its number and its price but I want that if I encounter the same item again to add its number to the existing number I have
I figured out the first part but I can't get the second any one has any ideas ?
public static void main(String[] args) throws FileNotFoundException{
Scanner sc = new Scanner(new File("Groceries.txt"));
while(sc.hasNext()) {
String line=sc.nextLine();
Scanner ss = new Scanner(line);
if(ss.hasNextInt()) {
ss.next();
}
while(ss.hasNext()) {
String name=ss.next();
int number = readInt(ss);
double price = ss.nextDouble();
System.out.printf("The item is %s its number is %d and its price is %.1f\n",name,number,price);
}
}
}
public static int readInt(Scanner sc) {
while(!sc.hasNextInt()) {
sc.hasNext();
}
return sc.nextInt();
}
Create a container object like so:
public class Container
{
private String item;
private double cost;
...
}
Use a HashMap<Container, Double> as your data structure. Every time you come across a duplicate, update its value.
If there is a possibility for an arbitrary amount of repeats, you can use do the following:
public class ValueContainer
{
private int count;
private double value;
}
and have a HashMap<Container, ValueContainer>, and update accordingly. There seems to be some confusion between what you say in the question and in a comment. Regardless, with simple substitutions, this construct will get you to where you want to go.
Create a class describing the attributes of your item (name, price, quantity , count etc).
Create a list of items (Yes, use generics..) // u can also use a map instead of a list..
Now, with each line you read from the text file, first get the item name using split().
Check if the item is already present. If yes, take it out, increment its count and put it back. if No, then add a new item to the list.
Happy Coding...

Adding an Object to an Object Array

Goal: Add a new Movie object to an existing Movie[] if there is room to add.
Code:
// Create the new Movie object
Movie movieToAdd = new Movie (newTitle, newYear);
// Add it to the Array
count = addMovie(movieList, movieToAdd, count);
Method Code:
public static int addMovie (Movie[] movieArray, Movie addMe, int count)
{
if (count != movieArray.length)
{
count++;
movieArray[count] = addMe;
System.out.println("Movie added successfully!");
}
else
{
System.out.println("Array size of " + movieArray.length + " is full. Could not add movie.");
}
return count;
}
QUESTION:
Currently, when the movieList array is printed out, the new entry prints as null even though the created Movie object will print just fine outside of the way. Therefore, I'm assuming the best way to add the addMe object into the array is to create a second new Movie object initialized within the array and build it piece by piece (so addMe will remain in memory, and a "copy" of addMe will be set into the array).
This to me doesn't feel very efficient (I hate extra data laying about...). Is there a better way to do this?
NOTE: The Movie object actually has 10 private data members. For this exercise I only needed to pass in two parameters and set defaults for the rest. You can imagine why I don't to use ten GET statements to build this array and have extra objects stuck in memory...
EDIT:
Current Print Out (Portions):
Menu options:
1. Show all movies:
2. Show movies sorted - manual
3. Show movies sorted - auto
4. Show Movie by Index
5. Search for movie Linearly
6. Search for movie using Binary Search
7. Add a movie
20. Quit
Please choose an option from the menu: 1 to 20:
7
Let's add the information for the new movie. Give me a Title and 4-digit Year, and I'll fill in the rest.
Title?
Me
Year of Release?
Please enter a valid 4 digit year: 1000 to 9999:
1213
Movie added successfully!
Menu options:
1. Show all movies:
2. Show movies sorted - manual
3. Show movies sorted - auto
4. Show Movie by Index
5. Search for movie Linearly
6. Search for movie using Binary Search
7. Add a movie
20. Quit
Please choose an option from the menu: 1 to 20:
25 | Les Vampires (1915) | Louis Feuillade | "Edouard Mathe, Marcel Levesque" | 1915 | 0 | http://www.imdb.com/title/tt0006206/ | http://www.guardian.co.uk/film/movie/117077/vampires | France | Horror | 175
null | 176
=============================================================================
MORE EDITS:
Constructor and Setters code - all this SHOULD be working right though.
public Movie (String t, int y)
{
// passed in
this.title = setTitle(t);
this.year = setYear(y);
// defaults
this.ranking = 0;
this.director = "No Director";
this.actors = "No Actors";
this.oscars = 0;
this.linkIMDB = "No IMDB Link";
this.linkGuardian = "No Guardian Link";
this.country = "No Country";
this.genre = "No Genre";
}
public String setTitle (String newTitle)
{
if (newTitle == null)
{
this.title = "No Title";
}
else
{
this.title = newTitle;
}
return this.title;
}
public int setYear (int newYear)
{
if (newYear >= 999 && newYear <=10000)
{
this.year = newYear;
}
else
{
newYear = 0000;
}
return this.year;
}
It isn't clear what you are asking, but this portion is incorrect:
count++;
movieArray[count] = addMe;
What if movieArray.length is 10, and count is 9? Then it will pass the count != movieArray.length check and then you will try to assign the element at index 10. Use post increment:
movieArray[count++] = addMe;
GOT IT!
I was using Count to set the index at which the new movie was stored.
Original count was 176.
Last index was 175.
I was increment BEFORE setting the movie, so the movie was being set at index 177.
So 176 was getting skipped.
It was only printing to 176 because that was the actual count, which wasn't accounting for the skipped space (there was an extra object in the array that wasn't getting printed).
(Figured this out when I attempted adding 2 new Movie objects to the array and got a null and then the first object only on print).
Solved by switching the set and the increment:
if (count <= movieArray.length)
{
movieArray[count] = addMe;
count++;
System.out.println("Movie added successfully!");
}

Sort an String-Array in the right order

I have tried to sort my array in the right order. I have stored 3 variables (1 int, 1 String, 1 float) in one field of the array. I have tried to use the native sort method, but my output is not sorted the right way:
[1 ,Agavendicksaft ,0.180
, 1 ,Agavendicksaft ,0.284
, 100 ,Röstzwiebel ,0.057
, 103 ,Salz fein ,6.220
, 103 ,Salz fein ,6.452
, 104 ,Salz grob ,0.490
, 114 ,Sesam ,0.735
, 114 ,Sesam ,1.742
, 115 ,Soja Granulat ,43.788
, 116 ,Sonnenblumenkerne ,0.267
, 116 ,Sonnenblumenkerne ,3.636
, 12 ,BAS hell ,0.975
, 12 ,BAS hell ,6.996
, 139 ,Vanille Aroma ,0.068
, 140 ,Weizenmehl Type W1600 ,1.163
, 140 ,Weizenmehl Type W1600 ,1.927
, 141 ,Weizenmehl Type W700 ,138.127
, 141 ,Weizenmehl Type W700 ,45.158
, 142 ,Walnüsse ,0.228
, 144 ,Wiechert Glutenfei ,1.160
, 145 ,Wienerwurst Stange ,0.100
, 150 ,Zitronen Aroma ,0.068
, 151 ,Zucker Normalkristall ,1.039
, 153 ,Wasser ,167.202
, 21 ,Dinkel Flocken ,0.347
, 24 ,Eier ganz ,0.453
, 26 ,Eigelb ProOvo ,0.365
, 29 ,Fenchel ganz ,0.105
, 36 ,Hafer ganz ,3.078
, 47 ,Hirse ganz ,0.133
, 49 ,Honig ,0.186]
So I have two questions:
How could I sort the array right?
How could I combine multiple entries to one entrie? f.e. not 140, 1.163 140, 1.927 => 140, 3,09 (I cannot do that earlier in my code because the array is a combination of 3 sql-result-arrays)
Here is my code:
s = Results2String(resultSet);
splitResult = s.split("/");
System.out.println(s);
s = null;
s = Results2String(resultSet2);
splitResult2 = s.split("/");
System.out.println(s);
s = null;
s = Results2String(resultSet3);
splitResult3 = s.split("/");
System.out.println(s);
System.out.println(splitResult3[0]);
preResult = new String[splitResult.length + splitResult2.length];
System.arraycopy(splitResult, 0, preResult, 0, splitResult.length);
System.arraycopy(splitResult2, 0, preResult, splitResult.length, splitResult2.length);
System.out.println(Arrays.toString(preResult));
result = new String[splitResult.length + splitResult2.length + splitResult3.length];
System.arraycopy(preResult, 0, result, 0, preResult.length);
System.arraycopy(splitResult3, 0, result, preResult.length, splitResult3.length);
Arrays.sort(result);
System.out.println(Arrays.toString(result));
I assume that one of each int, String and float belong together.
So you should put them in one class and implement Comparable (documentation):
public class Food implements Comparable<Food> {
private int id;
private String name;
private float score; // or maybe kcal... ?
public Food(int id, String name, float score) {
this.id = id;
this.name = name;
this.score = score;
}
#Override
public int compareTo(Food other) {
return id - other.getId();
// use the following if you want to sort by name instead
// return name.compareTo(other.getName());
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
Then you can sort an array of Foods....
How to use
I'm still not sure what your resultSets are (and why you have three of them) but I assume that they are ResultSets from a database query. Furthermore I assume that the id-name-score-combinations are actually rows in a database.
You could then go through those ResultSets and put the values of each row in a Food object:
ResultSet resultSet; // filled somewhere else
List<Food> food = new ArrayList<Food>();
while (resultSet.next()) {
int id = resultSet.getInt(0); // assuming the ids are in the first column
String name = resultSet.getString(1); // assuming the names are in the second column
float score = resultSet.getFloat(2); // assuming the scores are in the third column
food.add(new Food(id, name, score));
}
Collections.sort(food);
I hope this helps...
However, if your resultSets are really ResultSets from a database query, then you should probably sort your values in your SQL query with ORDER BY...
You need to write a comparator method and use the Collections.sort(List<T>, Comparator<? super T> method. Here is a link to the Collections java doc online.
inside your comparator, split the line into 3 parts (int, string, float) and compare them as you see fit.
Create an class with those three attributes.
public class Example{
private int field1;
private String field2;
private double field3;
.....
}
Fill you array with Objects made of this class then sort your array with a Comparator for this class that compares the String.

Categories

Resources