This question already has answers here:
How to compare two java objects [duplicate]
(5 answers)
Closed 9 years ago.
I am trying to search through a collection of an ArrayList if pairs. What I want to be able to do, is to go through the collection and find the first value in a pair and return the second value of that pair. The problem I am having is that the check I have to find the first value doesn't seem to be working, so every time I search, I end up returning null. I know that the problem exists with my if statement, but I cannot seem to sort out what it is I am doing wrong. Since this is a homework assignment, I can't show all the code to my pair class, or my pair list class, but I can show you the method I have for searching the first value:
public S findFirst(F firstValue) {
Iterator<Pair> myIter = this.iterator();
S tmp2 = null;
while (myIter.hasNext()) {
Pair tmp1 = myIter.next();
if (tmp1.getFirst() == firstCall) {
tmp2 = (S) tmp1.getSecond();
}
}
return tmp2;
}
If I throw in an else statement that just calls what I am attempting to do in my if check, like this:
else{
tmp2 = (S) tmp1.getSecond();
}
then whenever I test for the first value, I get the second value, so I know I am at least on the correct path, but I am assuming that I am doing something wrong with what I am checking for in my if statement. Does anyone know how I can correctly do this, (and please bear in mind that this is homework, so a guide to how to figure this out is far more valuable to me than just some random answer, I want to learn, not just be given an answer) Thanks in advance!
Don't use == to compare objects. Override and use equals().
I think
if (tmp1.getFirst() == firstCall)
should probably say
if (tmp1.getFirst().equals(firstValue))
The important difference is that == checks whether two expressions refer to the exact same object. You're more interested in knowing whether your two expressions actually refer to objects that are equal.
Try this:
if (tmp1.getFirst().equals(firstValue))
instead of
if (tmp1.getFirst() == firstCall)
Also you can override your own equals method.
You should never use == to compare objects.
Check How to compare two java objects
What Matt says, (don't use == ) but I think a bigger problem is that you don't return the 'first' encounter.... your if statement should look like:
public S findFirst(F firstValue) {
Iterator<Pair> myIter = this.iterator();
while (myIter.hasNext()) {
Pair tmp1 = myIter.next();
if (firstValue.equals(tmp1.getFirst())) {
return (S) tmp1.getSecond();
}
}
return null;
}
Related
This question already has answers here:
How to tell a Mockito mock object to return something different the next time it is called?
(5 answers)
Closed 2 years ago.
I am new to using Mockito. In my logic I need to mock a function that is inside the loop and for every iteration, it should return different value.
Example :
for(value : values )
{
int i = getValue(value);
i=i+1;
}
if(i=somevalue)
{
some code
}
else
{
Some other code
}
So if I mock getValue() method to return a particular value. Everytime, it is returning the same value and only one part of if else is covered.
Can you please suggest me a way such that everytime in the loop getValue() is returned different value.
Thank you !
Since you have an input in getValue() you can use that.
when(mockFoo.getValue(value1).thenReturn(1);
when(mockFoo.getValue(value2).thenReturn(2);
when(mockFoo.getValue(value2).thenReturn(3);
But if you just don't care you can return different values in a sequence.
when(mockFoo.getValue(any()))
.thenReturn(0)
.thenReturn(1)
.thenReturn(-1); //any subsequent call will return -1
// Or a bit shorter with varargs:
when(mockFoo.getValue())
.thenReturn(0, 1, -1); //any subsequent call will return -1
Also please note, that if(i=somevalue) will always be true, you might want to use if (i == somevalue).
So I have a method (of which I can't change the parameters, or else this could have been made easier through HashMaps...more on this later), that passes an item as a parameter. Now I have a list of instances from this other class, of which one of its attributes is of the same type of this item, and I want to find the instances in the list which correspond to this item (of which there should be only one). This is what I did to find this:
List<Instance> instances = ...
public static void checkItems(Item i) {
List<Instance> n = new ArrayList<>();
instances.forEach(p -> n.add(p.i == i ? p : null));
Instance currentInstance = n.get(0);
//Instance currentInstance = instances.stream().filter(p -> p.i == i).collect(Collectors.toList()).get(0);
}
You'll probably notice two things straight up:
I used a conditional operator which adds a null value to the list when the condition isn't passed
My commented code which was another attempt to solve this issue
So in the first case, I put null because it requires you to put something, and a null value is probably easier to work with, which is why the question arises: How do I access the first non-null value in a list (without resorting to iterating over the entire list to find it...)?
You may notice that I just assign the first value of the list with n.get(0) to currentInstance, because I know that only one value will have passed the test. However, due to some other code that I apply to currentInstance, this value cannot be null.
Just a note on the second point: the way I tried to solve it with streams actually works exactly as planned, except that for some reason the list of instances recovered is not a direct copy of the original instances. This resulted in the values of some of the attributed to have been reset to default values, therefore rendering this method useless.
EDIT: I just wanted to mention that the streams method wasn't working because of some silly mistake that I made in another class, there was nothing wrong with the code so I'll be using that bit to solve my problem :D
If you know that only one p passes the test, I don't know what the point of creating a list with a load of null values plus p is.
Your problem seems to stem from wanting to use forEach. In my opinion, you should almost always use a for loop in preference to forEach. With a simple for loop you can just use break when the item is found.
In detail:
Instance p = null;
for (Instance q : instances) {
if (q.i == i) {
p = q;
break;
}
}
if (p == null)
throw new IllegalStateException(); // It wasn't there.
// Do something with p.
You could do it this way:
Instance currentInstance = instances.stream()
.filter(p -> p.i == i)
.findFirst()
.get(); // you can use get if you are sure there's one instance
The predicate p -> p.i == i seems suspicious. Why not using equals() instead?
As described, this would normally be solved with streams in the following way:
Optional<Instance> first =
instances.stream().filter(p -> p.i == i).findFirst();
(of which there should be only one)
Of which there definitely is only one, or of which there might be more than one. (And if there's more than one, then what? Is that an error?) It sounds like it might be that you should have a Set<Instance>, not a List<Instance>. Just an observation.
You can do it like
instances.forEach(p -> {
if (p.i == i) n.add(p);
});
This question already has answers here:
Is there any reason for Eclipse showing assignment variables in while loops as valid?
(5 answers)
Closed 8 years ago.
Take a look on the following java code.
String Remark="";
boolean Paid, PartiallyPaid, NotPaid;
if(Paid=true) {Remark="Paid";}
if(PartiallyPaid=true) {Remark="Partially Paid";}
if(NotPaid=true) {Remark="Not Paid";}
Here the Boolean values determined by RadioButtons. I want to assign the string "Remark" as mentioned above. But It always giving the last assigning value only(as "Not Paid"). Anyone explain why this is occurring?
use == instead of = for comparison.
== is used to compare two values for equality
= is used for assigning one value to another
String Remark="";
boolean Paid, PartiallyPaid, NotPaid; // initialise values else compile error, pointed out by Peter O.
if(Paid==true) {Remark="Paid";}
if(PartiallyPaid==true) {Remark="Partially Paid";}
if(NotPaid==true) {Remark="Not Paid";}
As pointed out by unholysampler
for boolean values you dont have to explicitly check for equality. Following would do
String Remark="";
boolean Paid, PartiallyPaid, NotPaid; // initialise values else compile error, pointed out by Peter O.
if(Paid) {Remark="Paid";}
if(PartiallyPaid) {Remark="Partially Paid";}
if(NotPaid) {Remark="Not Paid";}
You have to use double equals in the if statement.
Here, if(Paid=true) should be if(Paid==true). Same thing with all other similar cases. = is assignment. You're giving Paid a value of true. == is a test for equivalence of primitive types. It should look like this:
String Remark="";
boolean Paid, PartiallyPaid, NotPaid;
if(Paid) {
Remark="Paid";
} else if(PartiallyPaid) {
Remark="Partially Paid";
} else if(NotPaid) {
Remark="Not Paid";
}
However, your booleans are all currently false. And it seems that simultaneously it can be be all 3 options, which is not a good idea. You should look up if/else statements in Java documentation.
I am working on a Single choice and Multiple choice test.
I have couple of questions and 4 answers for each question.
I am shuffling the answers as each answer is assigned to radio button.
This is how i am shuffling the arraylist where Random is a arraylist with items and r1,r2,r3,r4 are radio buttons.
random.add(val);
Collections.shuffle(random);
r1.setText(random.get(0));
r2.setText(random.get(1));
r3.setText(random.get(2));
r4.setText(random.get(3));
I am able to display the answers in jumbled way but when i select the answer i need to show that the answer is correct or wrong.
Sample question and options.
1. which language is used for android programming?
A.PHP
B.JAVA
C.C
D.C++
Correct answer is B i need to display that correct answer is B.
How to acheive this.
EDIT:
I have tried this:
Onclick of each radio button assign the value A and compare the value with xml value if its correct display correct but when i jumble its will not work.
EDIT 2
xml
<Question no="1" text="Which Programming language is used in android develoment" type="SCA" noc="4" jumble="NO" correctans="PHP">
<choice a = "PHP" flag="A">
<choice b = "JAVA" flag="B">
<choice c = "C" flag="C">
<choice d = "C++" flag="D">
You can create a hashmap with Option-isOptionCorrect pair. Like for your case:
HashMap<String, Boolean> choices = new HashMap<String, Boolean>();
choices.put("PHP", false);
choices.put("JAVA", true);
choices.put("C", false);
choices.put("C++", false);
Now shuffle the key-value pairs. Your correct choice will be one which has value true in the HashMap.
Egor is clear for what he is suggesting but I'll let you work with your current implementations.
class Option{
//You can add any other parameters if required.
String optionText;
boolean isAnswer;
}
// Use arraylist of Option class like this
ArrayList<Option> options = new ArrayList<Option>(); // in your case random
// Now suffle it.
Collections.shuffle(options);
// get the user selected option and verify using.
if(options.get(userSelectedOptionPosition).isAnswer){
//show "You are Correct!"
}else{
// show "You are In correct!"
}
Hope this will help you.
Here is a somewhat naive solution but it should work.
class Question {
String message;
String answer;
List<String> options; //"Java", "PHP", etc
}
Shuffle the keys of the Map in your Question object
In your radio buttons, do something like r1.setText(random.get(0))
On click, do
String choice = null;
for (RadioButton rb : rBtns) {
if (rb.isSelected) {
choice = rb.getText(); break();
}
}
if (choice.equals(question.getAnswer))
return true; //correct
else
return false; //wrong
The best approach here is not to operate with Strings, but to create a Question class, which will contain all the info about a question: its value, list of answers and the index of the right answer. When parsing the XML, create a list of Question objects and then work with them. There won't be any mapping problems anymore. Hope this helps.
You can hold your answers in your 'random' arraylist in a model, instead of pure strings;
private class AnswerModel {
string answer;
boolean flag;
//... getters and setters...
}
Here you can set your true answer' s flag to true, and all others to false. That way, you can simply return if the answer was correct.
There are already several good answers here. But another option is to write your own shuffle function. The shuffle algorithm is a very simple algorithm that runs in linear time, at least for arrays. By writing your own shuffle function, you can keep track of where the correct answer ends up.
To make this simple, I'm posting code that returns the new index of a specified index in a shuffled collection. The function mutates (alters) the original collection, so this should work.
/**
* #return Returns the new index of the element that was placed at correctIndex,
* or -1 if the correctIndex parameter was out of bounds.
*/
public int shuffleAnswers(Collection<String> collection, index correctIndex) {
String[] shuffleArray = new String[collection.size()];
int returnValue = -1;
collection.toArray(shuffleArray); // Convert to array
collection.clear(); // We have to add the elements again later
// Pick random elements
for (int i = shuffleArray.length; i > 0; i--) {
int randIndex = Math.random() * i;
if (returnValue == -1 && randIndex == correctIndex) {
// This only works if elements are added to the end
// So you may want to limit the function to ArrayLists or LinkedLists
returnValue = collection.size();
}
// Add the randomly selected element to the collection
collection.add(shuffleArray[randIndex]);
// We must ensure that we don't lose elements
// So we swap them down from the end
shuffleArray[randIndex] = shuffleArray[i - 1];
}
return returnValue;
}
Note like the comments say, this only works with collections that add elements to the end of the collection, and that fills arrays from the first to last element added to the collection.
This is perhaps slower than the other solutions, but note that you require a shuffle anyway, so it shouldn't affect running speed much.
Another option is just to have a correctAnswer String and then compare the user's choice to the string (with .equals()).
This is what would I do.
Since you are remembering answer in your XML file and not answers position, then on selected radio button take text (in this case it would be "PHP", "Java", "C++" or "C") and compare it with correct answer.
Jumbling can't affect on this, otherwise you are doing something wrong.
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);
}
}