Struggling to understand how to loop over a list - java

I'm currently developing a POS till system as a university assignment and I'm completely stumped on a for loop that I need to implement to save any data that gets added to the system by the end user. The save() function is meant to save any data put into the program to 1 of 2 .txt files (stock or till).
I've currently built the save function for each of the different instance variables but when it runs through the save() method it'll only run once (obviously) and I'm having a hard time understanding how to implement a sample for loop as a solution.
Here's my current progress:
public void save() throws IOException {
// IMPLEMENTATION
PrintWriter outfileStock = new PrintWriter(new FileWriter(SHOP_STOCK_DATA_FILE));
outfileStock.println(barcode);
outfileStock.println(cost);
outfileStock.println(quantity);
outfileStock.close();
PrintWriter outfileTill = new PrintWriter(new FileWriter(SHOP_TILL_DATA_FILE));
outfileTill.println();
outfileTill.println();
outfileTill.println();
outfileTill.close();
}
The sample for loop we've been given (from a worksheet that lead up to this assignment is this:
public void save(String fileName) throws IOException {
PrintWriter outfile = new PrintWriter(new FileWriter(fileName));
outfile.println(type);
outfile.println(face);
outfile.println(hair);
outfile.println(powerPoints);
outfile.println(loot.size());
for (Treasure treasure : loot) {
outfile.println(treasure.getName());
outfile.println(treasure.getValue());
}
outfile.close();
While I'm not asking for the code to be written for me, it would be great if somebody to explain how the
for (Treasure treasure : loot) {
outfile.println(treasure.getName());
outfile.println(treasure.getValue());
}
loop works. I can provide some more info if needed, fairly new to Java so not sure how much is needed to understand.

loot is an ArrayList that contains Treasure objects.
for (Treasure treasure : loot) {
outfile.println(treasure.getName());
outfile.println(treasure.getValue());
}
loops over each one of the Treasure objects (each one of which are temporarily assigned to treasure) by this line of code:
for (Treasure treasure : loot) {
which means (for every Treasure object in loot which you call treasure)
and gets (for each) their name (treasure.getName()) and their values (treasure.getValue()).
:
stands for the enhanced for-loop which was introduced in Java SE 5.0. See more info here:
https://blogs.oracle.com/CoreJavaTechTips/entry/using_enhanced_for_loops_with
Basically, instead of
for (int i=0; i < array.length; i++) {
System.out.println("Element: " + array[i]);
}
you can now do
for (String element : array) {
System.out.println("Element: " + element);
}

loot seems to be a List of some sort. What the for loop will do is take each element of this list and return them to you as a single object called treasure. when you get this element back you can treat is as a normal Treasure object. In your case it seems to be writing the treasure name and value to a file.
For each loop

This is basic Java. The variable loot is something that can be iterated over. It's either an array or one of the container classes like ArrayList. It contains Treasure objects.
For each element in the loot array, those two lines of code are executed.

loot is a List. Therefore using this enhanced for loop it fetch the each element in each iteration and assign it to the treasure variable. But here you don't have access to the previous element of the list in a given time. If you use other for loop for(int x=0; x < size ; x++ ) in each iteration you can access previous or next element by coding `loot.get(x-1) or loot.get(x+1). Therefore it depends on your requirement.

Related

Array is re-initialized every time

Hi i am trying to add the values to list as show in below code. i am getting error.
if i use like below
for (String n2 : number ) {
List<String> ARRAY = new ArrayList<String>();
if (!ARRAY.contains(n2)) {
Email(n2);
ARRAY.add(n2);
}
}
if i am using above. Though already email sent with value n2 again it is sending again. For first it has to sent but for second time n2 should be in array but still it sending. any one help. if n2 is passed to email second time it should not pass.
I am re-posting question as pervious one seems not clear i guess.
You need to move the ARRAY outside of the for loop
List<String> ARRAY = new ArrayList<String>(); // maybe as a class field
for (String n2 : number ) {
if (!ARRAY.contains(n2)) {
Email(n2);
ARRAY.add(n2);
}
}
List<String> ARRAY = new ArrayList<String>();
This line needs to be outside of your loop.
Why?
Simple. It's an issue of scope. Scope is the the lifetime and accessibility of a variable. In this case, you declare it inside of a loop, so the scope of that variable is, you guessed it, the loop. When the loop exits, the variable is destroyed.
You need to move it outside, so that the variable persists for the lifetime of the loop.
Extra Reading
Please, read the Java Naming Conventions.

Comparing strings from a written file

I'm stuck on this program I'm making for school. Here's my code:
public static void experiencePointFileWriter() throws IOException{
File writeFileResults = new File("User Highscore.txt");
BufferedWriter bw;
bw = new BufferedWriter(new FileWriter(writeFileResults, true));
bw.append(userName + ": " + experiencePoints);
bw.newLine();
bw.flush();
bw.close();
FileReader fileReader = new FileReader(writeFileResults);
char[] a = new char[50];
fileReader.read(a); // reads the content to the array
for (char c : a)
System.out.print(c); // prints the characters one by one
fileReader.close();
}
The dilemma I'm facing is how can I sort new scores with the scores in writeFileResults by the numerical value of int experiencePoints? If you're wondering about the variables userName is assigned by a textfield.getText method, and an event happens when you press one of 36 buttons which launches a math.Random statement with one of 24 possible outcomes. They all add different integer numbers to experiencePoints.
Well, I don't want to do your homework, and this does seem introductory so I'd like to give you some hints.
First, there's a few things missing:
We don't have some of the variables you've given us, so there is no type associated with oldScores
There is no reference to userName or experiencePoints outside this method call
If you can add this information, it would make this process easier. I could infer things, but then I might be wrong, or worse yet, have you learn nothing because I did your assignment for you. ;)
EDIT:
So, based on extra information, you're data file is holding an "array" of usernames and experience values. Thus, the best way (read: best design, not shortest) would be to load these into custom objects then write a comparator function (read: implement the abstract class Comparator).
Thus, in pseudo-Java, you'd have:
Declare your data type:
private static class UserScore {
private final String name;
private final double experience;
// ... fill in the rest, it's just a data struct
}
In your reader, when you read the values, split each line to get the values, and create a new List<UserScore> object which contains all of the values read from the file (I'll let you figure this part out)
After you have your list, you can use Collections#sort to sort the list to be the correct order, here would be an example of this:
// assuming we have our list, userList
Collections.sort(userList, new Comparator<UserScore>() {
public int compare(UserScore left, UserScore right) {
return (int)(left.getExperience() - right.getExperience()); // check the docs to see why this makes sense for the compare function
}
}
// userList is now sorted based on the experience points
Re-write your file, as you see fit. You now have a sorted list.

Monster object deletion

Short introduction:
I'm building a game, where monsters spawn at the top, and moves through a path, to the reach a point where they need to be removed/destroyed/deleted. But I can't seem to get the Monster Object deleted.
for (Monster i : Monstre)
{
this.add(i); //adds monster to JPanel
if(i.monstery > 50 && i.monsterx > 50){ //check if monster have reached end point
this.remove(i); //Should remove Object from the JPanel ?
i = null; //Sets object too null
Monstre.remove(i); //Removes object from arrayList "Monstre".
}else{
//Update the monsters bounds
The above removes the object from the JPanel, and it seems to be all good. But when i call System.out.println(Monstre.size()); I get an increasing amount of monsters spawned, and if increasing the monster spawn rate, the program starts to eventually slow down, because amount of monsters in the Monstre arraylist is over 9000, and never decreasing.
What I'm looking for, is a way to remove these objects while the game is running.
Remove the i = null; line. This is not C and you don't have to assign your variables to null. JVM will do that for you (google "java garbage collection"). Because of that line, you practically call Monstre.remove(null) which does not work.
Also, you cannot iterate over the collection in that manner and modify it (remove values). Save the monsters you want to delete in an array outside of the scope of the loop, and remove them after the loop finishes. Otherwise, use an iterator:
Iterator<Monster> it= Monstre.iterator();
while (it.hasNext()) {
Monster i= it.next();
//code code code
if (shouldDelete) {
this.remove(i);
it.remove();
}
}
In addition to the suggestion in the first answer, you should change your loop. Removing items from the Monstre list while using the for-each loop will cause problems.
Instead try :
Iterator<Monster> iter = Monstre.iterator ();
while (iter.hasNext())
{
i = iter.next();
this.add(i); //adds monster to JPanel
if(i.monstery > 50 && i.monsterx > 50){ //check if monster have reached end point
this.remove(i);
iter.remove();
}else{
EDIT :
Here's an explanation where you can't use the for-each loop :
So when should you use the for-each loop? Any time you can. It really
beautifies your code. Unfortunately, you cannot use it everywhere.
Consider, for example, the expurgate method. The program needs access
to the iterator in order to remove the current element. The for-each
loop hides the iterator, so you cannot call remove. Therefore, the
for-each loop is not usable for filtering. Similarly it is not usable
for loops where you need to replace elements in a list or array as you
traverse it. Finally, it is not usable for loops that must iterate
over multiple collections in parallel. These shortcomings were known
by the designers, who made a conscious decision to go with a clean,
simple construct that would cover the great majority of cases.
i = null; //Sets object too null
Monstre.remove(i); //Removes object from arrayList "Monstre".
Here you set the variable i to null then you request that i (i.e. null) is removed from your arraylist, the arraylist does not contain null so nothing happens. Setting things equal to null is very rarely nessissary.
As you have correctly said removing the i=null upsets the program, this is because you are iterating through the list and then changing the list while iterating, you have two options;
1) go through the Arraylist in a manor similar to an array
import java.util.*;
public class Test{
public static void main(String [] args){
ArrayList<Double> doubles=new ArrayList<Double>();
for(double i=0;i<10;i++){
doubles.add(i);
}
//remove 7.0s from doubles
for(int i=doubles.size()-1;i>=0;i--){
//must go through backwards - see http://stackoverflow.com/questions/12111210/java-arraylist-search-and-remove for why
if (doubles.get(i).equals(7.0)){
doubles.remove(i);
}
}
}
}
2) use an iterator and its remove method
import java.util.*;
public class Test{
public static void main(String [] args){
ArrayList<Double> doubles=new ArrayList<Double>();
for(double i=0;i<10;i++){
doubles.add(i);
}
//remove 7.0s from doubles
Iterator<Double> iterator=doubles.iterator();
while(iterator.hasNext()){
Double testDouble=iterator.next();
if (testDouble.equals(7.0)){
iterator.remove();
}
}
}
}
You cannot remove this element in a for-loop.
You need to use listIterator() method to retrieve an iterator that can be modified and loop with iterator-style. Otherwise you would always get java.util.ConcurrentModificationException

Java is not assigning values to my variables correctly, with linked lists

public void returnRental(Customer cust){
Rental toDelete = null; //Rental to be removed from list.
LinkedList<Video> toReturn = null; //List of videos to be added to inventory.
//Find appropriate rental according to customer name.
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
}
}
here is the snippet of code that is giving me problems. I've debugged it in eclipse quite a bit which ended up just confusing me more. It hits the if, and passes the condition. But once it gets to assigning values to "toReturn" it assigns it an empty list with size 0. Where as I check my rentals Linked list and the correct value are there, but for some reason it is not getting assigned to my variables correctly :( The same happens to "toDelete" but this isn't a list, it is one instance of my class Rental. (The linked list is a list of rentals, which contains a linked list of videos)
No errors are thrown...
Its a little difficult to explain, if you need more information please let me know and i'll clarify.
I'm at a loss, possibly because I'm not iterating through my linked list correctly?
Replace
if (cust.getName() == rentals.get(i).getRentee().getName()){
by
if (cust.getName().equals(rentals.get(i).getRentee().getName())){
You can't compare strings with == (except if your algorithm can ensure this is the same instance, which is almost never the case).
But the missing equals is not the only bug. It may be inside getRented() or elsewhere (you don't show what you do with toReturn and toDelete, so it's not clear if you don't have problems here).
Now, to go on chasing your bugs, you should either
debug, and put a breakpoint in your loop to check the state of rentals.get(i) and the execution at this point
if you can't debug, put a lot of System.println, so that you know what you have...
I've upvoted dystroy's answer because incorrect string comparison is always wrong.
But because that would fail differently (customer names not matching rentee names), I'm wondering if your issue is really caused by either of the following:
a problem in getRented(); or
cust having a null name on call, which would match a Rentee with a null name.
Possibly, your if condition is being hit more than once. First of all, check if this is actually happening. If so, check your logic and determine if you want to stop at the first occurence or at the last (this case seems to be the latter).
If you want to stop at the first occurence, break the iteration:
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
break;
}
}
for(int i = 0; i < rentals.size(); i++){
if(cust.getName().equals( rentals.get(i).getRentee().getName())){
toReturn.addAll(rentals.get(i).getRented());
//assumming it returns the list of Video object
toDelete = rentals.get(i);
}
}

Checking an object list with the same object list

I have a problem with checking objects in a list with the same objects. I have an object list with different type of objects like, bullets, enemies and random background objects.
Now I want to check if some objects collide with each other, like bullets with enemies.
The problem is that when I put the same for loop within the for loop with both the same objects, i don't get the behavior i was expecting... Anyone knows a better way to handle this?
The left image shows that bullets are not moving anymore, the right show the situation when i remove the loop within the loop.
https://www.dropbox.com/s/92tnxizxdneqgz3/ss1.png
EDIT: The different strings are read from a script, I am aiming for maximal flexibility. That is also the reason why I don't want different collections of each type of object. The collision was working when I did that.
for (Object o : objects) {
if (o.behavior.equals("aggressive")) {
o.aggressive(ship.x, ship.y, ship.z);
}
if (o.behavior.equals("missile")) {
o.missile();
if (o.type.equals("bullet_player")) {
for (Object n : objects) {
//doesn't matter what i put here
}
}
}
}
Solution:
I got it working, the problem appears to lie in nesting an for loop of an arraylist within an other. What i finally did is this: I cloned the arraylist, check the cloned list with the original object list, i check if the object is the same and if not I do the collision check.
The standard approach is this, which will compare each pairing once:
for(int i=0; i<objects.size(); i++)
for(int j=i+1; j<objects.size(); j++)
//.... compare objects[i] and objects[j] for collision etc
As your game world gets more complex, consider placing objects in a spatial index instead.
The nested loop shouldn't be a problem. The following example, where I have some iterators running on the same collection, works as expected:
public static void main(String a[]) {
List<String> strings = Arrays.asList("a", "b", "c");
for (String s: strings) {
for (String t:strings) {
System.out.println(s + "/" + t);
}
}
}
Looks to me like the problem is within your collision detection. You may have false positives (collisions detected where no collision happened)

Categories