This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I'm working on a program using eclipse that generates objects for runners in a 100 m race.
each runner has a lane, name and three separate times for completing the race.
However, when I try to generate the times for each object, I get java.lang.NullpointerException.
Here is the method for generating the times.
public double[] getTimes() {
for (int i = 0; i <= (times.length - 1); i++) {
rolled = 1.0 + roll.nextDouble() * 100.0;
// set rolled to a new random number between 1 and 100
times[i] = rolled;
// set index i of the array times to be the nearest
// double to roll's value.
}
return times;
}
and then the code in which the method is called.
public void testGetTimes() {
double[] times = performance.getTimes();
assertEquals(2, times.length);
assertEquals(9.2, times[0], 0.01);
assertEquals(9.4, times[1], 0.01);
}
I'd try to fix it through debugger, but every time i try to step-into the for loop, i get InvocationTargetException,(Throwable line: not available
initialization of times, roll and rolled:
public class Performance {
private int lane;
private String name;
double[] times = new double[3];
int rolling;
Random roll = new Random();
double rolled;
double average;
double best;
and of performance:
public class PerformanceTest {
Performance performance;
#Before
public void setup() {
performance = new Performance(1, "", new double[]{9.2, 9.4});
}
It looks like one of your objects is uninitialized. On the other hand, initializing it to null can cause the same problem. As of Java 8, I would suggest using an Optional to contain any values that you are not immediately certain of, or are not immediately aware of, and put their processing in an Optional.ifPresent(Consumable) statement. It minimizes the possibility of a NullPointerException, and invites functional programming methods, which will seriously slim down the amount of time it takes to get the job done.
As far as your assertion error goes, I'm sure you already know that this is only caused by an assert statement. Looks like times[0] is substantially larger than you were expecting. It appears, from what we can see, that you're setting it to 1.0 + random{0.0...1.0} * 100.0; I don't know what the precondition that leads you to expect 9.4 is, but this could easily hit the forties.
Related
This question already has answers here:
Java: Error: variable might not have been initialized
(2 answers)
Closed 6 months ago.
class HelloWorld {
public static void main(String[] args) {
int sum;
for (int i = 0; i < 10; i++) {
if (i == 9) {
sum = 10;
}
}
System.out.println(sum);
}
}
why this code gives this error?
HelloWorld.java:9: error: variable sum might not have been initialized
System.out.println(sum);
We can look at the code and intuitively reason that sum will always have a value by the time it's used, because the loop will always execute and one of the iterations will satisfy the if condition.
But the compiler doesn't intuitively reason any of that. It sees a loop and a conditional block and it can't guarantee that sum will have a value by the time it's used. To the compiler, it's possible that loops may iterate 0 times or that conditions may never be true.
Basically, we can "test the code" in our heads and predict its outcome. But the compiler doesn't test the code, no matter how simple the code may be.
You can correct the problem by simply initializing the value:
int sum = 0;
So I have this method that picks at random an object from a list of 2 objects. I would like to write a junit test (#Test) asserting based on a confidence level that somehow there's a 50% chance for each of the 2 objects to be picked.
The piece of code under test:
public MySepecialObj pickTheValue(List<MySepecialObj> objs, Random shufflingFactor) {
// this could probably be done in a more efficient way
// but my point is asserting on the 50% chance of the
// two objects inside the input list
Collections.shuffle(objs, shufflingFactor);
return objs.get(0);
}
In the test I would like to provide 2 mocks (firstMySepecialObjMock and secondMySepecialObjMock) as input objects of type MySepecialObj and new Random() as the input shuffling parameter, then assert that the firstMySepecialObjMock happens to be the choice 50% of the times and secondMySepecialObjMock happens to be the choice in the other 50% of the times.
Something like:
#Test
public void myTestShouldCheckTheConfidenceInterval() {
// using Mockito here
MySepecialObj firstMySepecialObjMock = mock(MySepecialObj.class);
MySepecialObj secondMySepecialObjMock = mock(MySepecialObj.class);
// using some helpers from Guava to build the input list
List<MySepecialObj> theListOfTwoElements = Lists.newArrayList(firstMySepecialObjMock, secondMySepecialObjMock);
// call the method (multiple times? how many?) like:
MySepecialObj chosenValue = pickTheValue(theListOfTwoElements, new Random());
// assert somehow on all the choices using a confidence level
// verifying that firstMySepecialObjMock was picked ~50% of the times
// and secondMySepecialObjMock was picked the other ~50% of the times
}
I am not sure about the statistics theory here, so maybe I should provide a different instance of Random with different parameters to its constructor?
I would also like to have a test where I could set the confidence level as a parameter (I guess usually is 95%, but it could be another value?).
What could be a pure java solution/setup of the test involving a confidence level parameter?
What could be an equivalent solution/setup of the test involving some helper library like the Apache Commons?
First of all this is the normal way to pick random elements from a List in Java. (nextInt(objs.size() produces random integers between 0 and objs.size()).
public MySepecialObj pickTheValue(List<MySepecialObj> objs, Random random) {
int i = random.nextInt(objs.size());
return objs.get(i);
}
You can read in Wikipedia about how many times you should perform an experiment with 2 possible outcomes for a given confidence level. E.g. for confidence level of 95% you get a confidence interval of 1.9599. You also need to provide a maximum error say 0.01. Then the number of times to perform the experiment:
double confidenceInterval = 1.9599;
double maxError = 0.01;
int numberOfPicks = (int) (Math.pow(confidenceInterval, 2)/(4*Math.pow(maxError, 2)));
which results in numberOfPicks = 9603. That's how many times you should call pickTheValue.
This would be how I recommend you perform the experiment multiple times (Note that random is being reused):
Random random = new Random();
double timesFirstWasPicked = 0;
double timesSecondWasPicked = 0;
for (int i = 0; i < numberOfPicks; ++i) {
MySepecialObj chosenValue = pickTheValue(theListOfTwoElements, random);
if (chosenValue == firstMySepecialObjMock) {
++timesFirstWasPicked;
} else {
++timesSecondWasPicked;
}
}
double probabilityFirst = timesFirstWasPicked / numberOfPicks;
double probabilitySecond = timesSecondWasPicked / numberOfPicks;
Then assert that probabilityFirst, probabilitySecond are no further than maxError from 0.5
I found a BinomialTest class in apache-commons-math but I don't see how it can help in your case. It can calculate the confidence level from the number of experiments. You want the reverse of that.
This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
I have a quick question that involves one ArrayList, 2 Iterators, and some nested for loops. Im trying to make a bit of a gravity engine using multiple gravity wells pulling on each other and moving around. To do this, Iv made an ArrayList of these gravity wells, all randomly places on the screen with a random size. Here it is for reference.
for(int i = 0; i < amount; i++){ // makes all
int mass = rand.nextInt(45,65);
int locX = rand.nextInt(50, getWidth()-100);
int locY = rand.nextInt(50, getHeight()-100);
Color cColor = rand.nextColor();
if(mass%8==0){
mass = rand.nextInt(25,35);
}
else if(mass%7==0){
mass = rand.nextInt(75,85);
}
Body body = new Body((double)locX,(double)locY,mass);
body.setFilled(true);
body.setColor(Color.WHITE);
body.setFillColor(cColor);
add(body);
bodys.add(body);
}
bodys is the name of the ArrayList containing everything. So my real problem comes to the Iterators. Heres the code thats giving me trouble:
public void move(){
Iterator<Body> eIter = bodys.iterator();
while(eIter.hasNext()){ // finding the thing we edit
Body edit = eIter.next();
int addX = 0, addY = 0;
int totalX = 0, totalY = 0;
double ex = edit.getX(), ey = edit.getY();
double eMass = edit.getMass(), eSize = edit.getHeight();
double eMoveX = edit.getMoveX(), eMoveY = edit.getMoveY();
int placeInArrayEdit = bodys.indexOf(edit);
Iterator<Body> fIter = bodys.iterator();
while(fIter.hasNext()){ // iterating through the force pulling the edit body
Body force = fIter.next(); /// ConcurrentModificationException is thrown
int placeInArrayForce = bodys.indexOf(force);
if(placeInArrayForce != placeInArrayEdit){ // making sure the 2 bodys arent the same
double fx = force.getX(), fy = force.getY();
double fMass = force.getMass();
double fMoveX = force.getMoveX(), fMoveY = force.getMoveY();
double difX = (ex-fx);
double difY = (ey-fy);
double distX = distanceP(ex, fx);
double distY = distanceP(ey, fy);
double vecX = (difX/distX);
double vecY = (difY/distY);
if(distance(fx,ex,fy,ey) <= eSize/3){ // if they are colliding
if(eMass >= fMass){
remove(edit);
edit.addMass((int)(fMass));
eIter.remove(); // problem
}
if(eMass < fMass){
remove(force);
force.addMass((int)(eMass));
fIter.remove();
}
}
double grav = (eMass/fMass);
grav -= (grav*.50);
addX -= (vecX/grav)/2; // this determines movement which means i
addY -= (vecY/grav)/2; // need to edit this with fMass
}
edit.setVelX(addX/(eMass + (eMass*.75)));
edit.setVelY(addY/(eMass + (eMass*.75)));
edit.addMoveX(edit.getVelX());
edit.addMoveY(edit.getVelY());
edit.move(edit.getMoveX(),edit.getMoveY());
}
}
}
The code above is moving the gravity wells and testing for collision. The problem is that ConcurrentModificationException is thrown where iv commented it to be thrown.
Iv spent about an hour or so looking around for a solution and nothing iv tried has worked. The code works up until the wells actually hit each other, then the error is thrown. Is there a way to avoid this error while still testing for collision like this, or is my code just too broken?
Thanks for all the help! Please let me know if you need anything clarified as this is my first question on StackOverflow
See javadoc of ArrayList:
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
So, you have 2 iterators: eIter for the outer loop, and fIter for the inner loop.
When you call eIter.remove(), fIter will go bad.
When you call fIter.remove(), eIter will go bad.
(If you had called bodys.remove(index), both would go bad.)
Either way, one of the iterators will be stale, and will throw ConcurrentModificationException when you call next().
Also, when you call eIter.remove(), you don't break out of the inner loop, so you run the risk of trying to do it again in another iteration of the inner loop.
In short, you need to find another way, e.g. using indexes and get(index) calls, or something like that.
This question already has answers here:
Random weighted selection in Java
(7 answers)
Closed 2 years ago.
So I am writing a program in part where a user can define as many random outcomes as they want. They also define the probability of each (so no, they are not equal). What is they best way to check which occured. Note: My program happens to be a Minecraft plugin, but the question is more of a general java one, so I am trying to make the code reflect that:
Map<String,Integer> possibilities = new HashMap<String,Integer>();
int x = (int) (Math.random() * 100)
My idea was to create another variable, and add the previous probability checked to it every time, and check if that was less than x. If it wasn't rinse and repeat, but I'm unsure of how to structure this.
So for is example: if the user configured it so he has 3 different outcomes, with a 30, 20, 50 percent chance respectively, how would I do this?
Use a NavigableMap, which will allow you to retrieve the correct outcome with one clean and simple lookup. (And internally, this uses an efficient O(log n) lookup—not that your maps will be large enough to matter.)
import java.util.NavigableMap;
import java.util.TreeMap;
import static java.util.concurrent.ThreadLocalRandom.current;
final class LoadedDie {
public static void main(String... argv) {
/* One-time setup */
NavigableMap<Integer, String> loot = new TreeMap<>();
int cumulative = 0;
loot.put(cumulative += 20, "Gold");
loot.put(cumulative += 30, "Iron");
loot.put(cumulative += 50, "Coal");
/* Repeated use */
System.out.println(loot.higherEntry(current().nextInt(cumulative)).getValue());
System.out.println(loot.higherEntry(current().nextInt(cumulative)).getValue());
}
}
Here's one way to do it.
public static String getOutcome(Map<String, Integer> possibilities) {
int x = (int) (Math.random() * 100);
for (Map.Entry<String, Integer> possibility : possibilities.entrySet()) {
if (x <= possibility.getValue()) {
return possibility.getKey();
}
x -= possibility.getValue();
}
// unreachable if probabilities are correctly mapped
return null;
}
The lifeCycle-method in my MatrixCreatureContainer-class throws a stack overflow error after about 3-4k iterations. Why is that? I assume it has something to do with memory allocation, but I cannot figure out how to solve it. I tried reading about the java garbage collector, but nothing I did seemed to help.
public class MatrixCreatureContainer {
private final static int NUMBER_OF_CREATURES = 20;
private static Random rand;
public static void main(String[] args){
rand = new Random();
List<MatrixCreature> population = new ArrayList<MatrixCreature>();
for(int i = 0; i < NUMBER_OF_CREATURES ; i++){
population.add(new MatrixCreature());
}
Collections.sort(population);
lifeCycle(population,0, 4000);
}
private static void lifeCycle(List<MatrixCreature> population, int generation, int iterations){
if (generation == iterations) return;
List<MatrixCreature> newPopulation = new ArrayList<MatrixCreature>();
while(population.size() != 0){
MatrixCreature mother = population.remove(rand.nextInt(population.size()));
MatrixCreature father = population.remove(rand.nextInt(population.size()));
newPopulation.add(new MatrixCreature(mother,father));
newPopulation.add(new MatrixCreature(mother,father));
newPopulation.add(new MatrixCreature(mother,father));
}
Collections.sort(newPopulation);
newPopulation = newPopulation.subList(0,NUMBER_OF_CREATURES);
lifeCycle(newPopulation,generation + 1, iterations);
}
}
The MatrixCreature-class basically only holds an integer array (int[]) of 20 integers. The constructor takes in two other matrixCreatures, and combines the arrays of two the matrixCreatures given, with a small chance of mutation. Each matrixCreature gets a score (where 0 is the best) of how close the sum of the numbers in the array is to 55. It's that score the population of each generation in the MatrixCreatureContainer is sorted by, such that the 20 "best" of each generation survives.
I can post the code to the MatrixCreature-class if it's relevant.
Thanks in advance :)
-Boye
With this call:
lifeCycle(population,0, 4000);
you're basically asking for a stack with 4000 frames (at least - see later). That isn't totally beyond reason, but in fact there's no reason to make this recursive at all. You can easily just change the method to be iterative - and even remove the generation parameter:
private static void lifeCycle(List<MatrixCreature> population, int iterations) {
for (int generation = 0; generation < iterations; generation++) {
// Body of previous method here
}
}
Additionally, you keep creating views using newPopulation = newPopulation.subList(...). You probably don't want to do that - it means that every operation will need to go through a huge number of stack frames, as each call to a view will delegate to its underlying list... and if that's another view, it needs to keep going, etc. Icky. If those view calls actually require a couple of stack frames per "layer" you could easily end up with a stack of around 12K calls in your original code...
I would suggest creating a copy of the relevant portion of the list on each iteration instead - and then returning the final list.
Each lifecycle starts with its own population and creates a new one for the next generation (with always 3 creatures inside; is this intended ?)
So after 4000 iterations you have those 4000 population lists hanging around as they never went out of scope.
Java does not support tail-recursion optimization, so your last line in the lifeCycle method creates a new stack frame for every iteration.
With your memory size, and the number of local variables, you have determined that you can have about 4000 stack frames. Solution: rewrite your method using a for-loop. It's a small change, you don't really need recursion for your method.