A segment of my code is triggering an infinite while loop, and I'm not sure why. I've used the loop itself before to add friends to a Linked List in this same program and it worked fine, so I do not understand why it is turning into an infinite loop now.
while (!a.equals("*")){
curr = friendlist.getUsers().getFront();
while (curr!=null){
if (curr.getData().getName().equals(a)){ //why is it not removing friends?
d.removeFriend(curr.getData());
}
curr = curr.getNext();
}
System.out.println("Add a friend by typing in their name. Enter * to end. ");
a = in.nextLine();
}
The above code accesses the following segment from another class:
public void removeFriend(User u){
if (friendsList.isEmpty()){
System.out.println("Empty list, cannot remove.");
}
else{
Node c = friendsList.getFront();
while (c.getNext()!=null){
if (c.getNext().getData().equals(u)){ //condition: if the data is the same
c.setNext(c.getNext().getNext()); //change the link
c.getNext().setData(null); //set the next data to null (cut the link)
friendsList.setSize(friendsList.size()-1);
c = c.getNext();
}
}
}
}
Why is the code not running properly?
As another poster has mentioned, you are invoking the getNext() method twice in one code block.
Here's what I presume is what will work for you
while (c!=null){
if (c.getNext().getData().oldestFriend().getBirthYear()>c.getData().oldestFriend().getBirthYear()){
a = c.getNext().getData();
continue; //then skip the current iteration, so that your line below after the if statement, wont get called.
}
c = c.getNext();
}
Why dont you do this, because now it looks like you're calling that same method three times!
Instead, store whatever is returned from the getNext() into one variable, and then access that local variable and do whatever you want with it, analyse is however you like etc.
Do you know where the infinite loop is exactly? Maybe put a System.out.println("loop") before curr.getNext() and c.getNext() so see which one is failing?
Would add this as a comment, but I'm not yet allowed to :(
How is the semantic of
allUsers.getFront()
Does it just fetch the head or is it more like a pop-operation?
In case of a fetch, there might be an issue with the recursive call of
oldestFriend()
in the method oldestFriend().
Though in that case I would expect a StackOverflowException.
change your while by:
while (c.hasNext() {
Node oldC = c;
c = c.getNext();
if(c.getData().oldestFriend().getBirthYear() > oldC.getData().oldestFriend().getBirthYear()) {
a = c.getData();
}
}
Call only getNext() if there is next, and only once.
Related
This is my code snippet:
public NaturalNumberTuple toSet()
{
int newTuple[] = new int[tuple.length];
boolean checkIfYouHadToRemoveSomething = false;
for(int i : newTuple){
newTuple[i] = tuple[i];
}
for(int i : newTuple){
for(int j : tuple){
if(newTuple[i] == tuple[j]){
NaturalNumberTuple placeholderTuple = remove(tuple[j]);
newTuple[i] = tuple[j];
checkIfYouHadToRemoveSomething = true;
}
}
}
if(checkIfYouHadToRemoveSomething){
return placeholderTuple;//Problem
} else {
return new NaturalNumberTuple(tuple);
}
}
The method is returning a new NaturalNumberTuple without the given Number (here tuple[j]).
My toSet() method should give me the same Array as I'm giving to it but with only one occurrence per number.
My problem is in the line marked with (//Problem).
The Problem is that placeholderTuple is not defined as a variable. I know it isn't, but if I write at the beginning of my method:
NaturalNumberTuple placeholderTuple;
and at the line where I originally defined my placeholderTuple:
placeholderTuple = remove(..);
it gives me an error that placeholderTuple may not been initialized yet.
I know why I'm getting those errors but I really don't know how to fix that.
If anyone is trying to optimize my code with ArrayLists, please don't because I'm not allowed to use them (not sure if they would help here but at other code snippets they would).
At the start of your method, write :
NaturalNumberTuple placeholderTuple = null;
This will keep this variable visible till the end of the method, and initialize it to a default value.
Then, inside the loop yo change :
NaturalNumberTuple placeholderTuple = remove(tuple[j]);
to
placeholderTuple = remove(tuple[j]);
Declare and initialize it in the begining of the code as:
NaturalNumberTuple placeholderTuple = null;
And in your loop, just initialize it without redefining like placeholderTuple = remove(tuple[j]); and it should work.
I think your code will always return the last entry of newTuple which is similar to tuple, so it doesnt makes sense to me. If you just want to remove very first match, you could do without two loop like:
placeholderTuple = remove(tuple[0]);
This is how I understand method getUser below :
Return a User object or null
Get a Set of users and assign them to userSer.
If the set is not empty begin iterating over the set but
return the first user within the set.
Here is the method :
private User getUser(UserDet arg)
{
Set<User> userSet = arg.getUsers(User.class);
if (CollectionUtils.isNotEmpty(userSet))
{
for (User user : userSet)
{
return user;
}
}
return null;
}
I think I could replace the method with this :
private User getUser(UserDet arg)
{
Set<User> userSet = arg.getUsers(User.class);
if (CollectionUtils.isNotEmpty(userSet))
{
return userSet.iterator().next();
}
else {
return null;
}
}
This new method removes the loop and just returns the first element in the set, same as original implemention. Is it correct?
Yes. Actually, it's pretty much almost the same thing, as a foreach loop is syntactic sugar for using an iterator from an Iterable.
Note, however, that you don't need the nonempty check in the first variant, since the loop won't iterate in the case of an empty set anyway.
yes both are same. in first implementation, control will return on first iteration of the loop from the function and consequently loop will end.
Yes it is correct, I'd even go for removing the CollectionUtils.isNotEmptySet and use the Iterator's hasNext method... If the set is guaranteed to be non-null.
It seems to be correct, but it will only make the method a bit easier to read, it will not optimize it in terms of performance. Still I think the change is good and you should do it.
Yes, it does pretty much the same, but if your spec says to start iterating then maybe you should - maybe this method will be extended in the future.
BTW: it is a good convention that your method has only one return statement (i.e. you can create a variable, which will be returned, assigned a null at the beginning and assign a user inside your loop)
Yes. Both the methods return the first element in the set. The first method seems to have been written for something else previously and changed then keeping the for loop intact.
In anycase, the second method that you're proposing won't give any significant performance benefit but should be a better way than the first one.
So in case, UserDet#getUsers(Class) never returns null (but an empty Set in case no user could be found), the shortest (and in my opinion most readable) form is:
private User getUser(UserDet arg) {
Set<User> userSet = arg.getUsers(User.class);
return userSet.isEmpty() ? null : userSet.iterator().next();
}
I would do this.
I won't run a loop and more over I'l add a null check.
private User getUser(UserDet arg) {
Set<User> userSet = arg.getUsers(User.class);
if (userSet != null && userSet.size() > 0) {
return userSet.iterator().next();
}
return null;
}
I'm working on a project for school but i'm a little stuck right now
My problem is that i have an arrayList of Squares
Each Square has a value(from 0 to 100). Its starting value is 9999 so i can check if its is checked.
If a square is checked i want it to be removed from the arrayList.
So after a while there will be no Squares left.
there is a little bit of code where the first value is set so thats why i check if the value is 9999.
But i get an error. One that i havent seen before.
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
Vak = Square
this is my code:
while (!vakken.isEmpty()) { // check if empty
Iterator itrVak = vakken.iterator();
while (itrVak.hasNext()) {
Vak vak = (Vak) itrVak.next(); // here is get the error
if (vak.getValue() != 9999) {// check if square value is 9999
Collection checkVakken = vak.getNeighbour().values();
Iterator itre = checkVakken.iterator();
while (itre.hasNext()) {
Vak nextVak = (Vak) itre.next();
if (nextVak != null) {
if (nextVak.getValue() == 9999) {
nextVak.setValue(vak.getValue() + 1); // set value by its neighbour
vakken.remove(vak);
checkvakken.add(vak);
}
}
}
} else {
vakken.remove(vak);
checkvakken.add(vak);
}
}
}
You are removing elements from the collection while you are iterating it. As the iterator may produce unpredictable results in this situation, it fails fast throwing the exception you encountered.
You may only alter a collection through the iterator's methods while traversing it. There should be remove method on the iterator itself, that removes the current element and keeps the iterator intact.
While iterating, you should use Iterator instance for removing object:
itre.remove();
You can try like this:
itre.remove();
ITERATOR never lets you modify when you are iterating.. you need to use loops instead.. this happens coz you are using the Iterator, same time other thread is modifying the list...
My dipslay function of linked list is as follows:-
public void display()
{
cur = first;
if(isEmpty())
{
System.out.println("no elements in the list");
}
else
{
System.out.println("elements in the list are:");
do {
System.out.println(first.data);
first = first.link;
} while(first.link!=null);
first=cur;
}
where curr and first are references of class node
public class node
{
int data;
Node link=null;
}
why is this function only printing the last element?
The function looks more or less correct. However why are you setting cur to first and then using first to do the iteration? Just use cur in the iteration so you don't have to reset first.
Check to make sure you're adding nodes into the list correctly. So if you think there are 3 elements in the list, run this in display():
System.out.println(first.data);
System.out.println(first.link.data);
System.out.println(first.link.link.data);
This is to check if your links are correct.
It is not possible to say for sure, but it is probable that your list actually contains only one element; i.e. that the code that creates the list is broken.
I should also point out that the display method should use a local variable to step through the elements. If you use an instance variable (e.g. first) you are liable to get different methods interfering with each other.
Finally, your test for the end of the list is incorrect. Think carefully about what first and first.link point at when the while test is executed.
I'm extending the LoadFunc. In the getNext function I'd like to skip returning a tuple under certain conditions - this way I could only load a sample of the data file. I tried returning null for the rows I don't want to return but the problem is that the method terminates after the first null Tuple is returned.
Does anyone know of a way to do this? Should I do it in a different method?
Thanks in advance.
(Assuming you mean LoadFunc in Pig ... )
I would suggest writing a new method that does what you want simply to not break the original documented use of the getNext() method.
You should look at the source for the Pig classes that extend LoadFunc and see how they implement getNext(). For example: TextLoader
From there it should be fairly trivial to do what you're trying to do.
Edit to try and offer a little more detailed help:
(This is using the TextReader as an example)
The getNext() method is reading from a RecordReader. It does this by calling RecordReader.nextKeyValue() to advance to the next record. You check to see if that's true (meaning it read a record) and if it is, you call RecordReader.getCurrentValue() to retrieve the value.
Lets say you only wanted every fifth one as a sample in getNext():
int count = 0;
Text myText = null;
whlie(myRecordReader.nextKeyValue() == true)
{
if (count == 4)
{
myText = (Text) myRecordReader.getCurrentValue();
break;
}
count++;
}
if (myText != null) // we didn't hit the end; we have a record
{
... // create the tuple
return myTuple;
}
else
return null;
(corrected my silly off-by-one mistake)