how to fix NullPointerException in generic circular array queue [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I am trying to create a basic airport simulation using two queues. They are supposed to alternate between taking off, and when one has no more 'planes' left, the NPE needs to be handled so that the other queue can continue going until the loop has finished and both queues have run out, as one has 7 entries and the other has 4. I thought if I tried to put an exception handler in the dequeue method it might fix it, but I have to use a generic class for it, so that didn't work properly. As of right now the for loop that is meant to dequeue runs until the 4th loop, which is when it stops, throws the NPE, and exits the program. So my question is, how can I make it so that when one queue runs out, it stops trying to loop it and instead continues looping the last queue?
Here is my main class where the loop is running:
public abstract class Airport<T> {
public static void main(String[] args) {
//creates separate queues
Driver<Integer> runway1 = new Driver<>();
Driver<Integer> runway2 = new Driver<>();
//adds 7 planes into runway 1
for (int i = 0; i < 7; i++) {
runway1.enqueue(i);
}
//adds 4 planes into runway 2
for (int i = 0; i < 4; i++) {
runway2.enqueue(i);
}
int size1 = runway1.length();
int size2 = runway2.length();
//run loop while either runway has planes left
while (size1 > 0 && size2 > 0) {
System.out.println("There are currently " + size1 + " planes waiting for takeoff in Runway 1.");
System.out.println("There are currently " + size2 + " planes waiting for takeoff in Runway 2.\n");
for (int lane = 0; lane < 7; lane++) {
int lane1, lane2;
if (runway1.isEmpty()){
System.out.println("Runway 1 is empty.");
}
else {
lane1 = runway1.getFront();
System.out.println("Plane " + lane1 + " has taken off from Runway 1.");
runway1.dequeue();
}
if (runway2.isEmpty()){
System.out.println("Runway 2 is empty.");
}
else{
lane2 = runway2.getFront(); //EDIT: npe occurs here
System.out.println("Plane " + lane2 + " has taken off from Runway 2.\n");
runway2.dequeue();
}
}
}
}
}
And here is the part of my driver class:
class Driver<T> implements Queue1<T> {
private static final int defaultSize = 10;
private int maxSize; // Maximum size of queue
private int front; // Index of front element
private int rear; // Index of rear element
private T[] listArray; // Array holding queue elements
/**
* Constructors
*/
Driver() {
this(defaultSize);
}
#SuppressWarnings("unchecked")
// For generic array
Driver(int size) {
maxSize = size + 1; // One extra space is allocated
rear = 0;
front = 1;
listArray = (T[]) new Object[maxSize]; // Create listArray
}
/**
* Put "it" in queue
*/
public void enqueue(T it) {
assert ((rear + 2) % maxSize) != front : "Queue is full";
rear = (rear + 1) % maxSize; // Circular increment
listArray[rear] = it;
}
/**
* Remove and return front value
**/
public T dequeue() {
assert length() != 0 : "Queue is empty";
T it = listArray[front];
front = (front + 1) % maxSize; // Circular increment
return it;
}
/**
* Return Front Value
**/
#Override
public T getFront() {
assert length() != 0 : "Queue is empty";
return listArray[front];
}
#Override
public T getBack() {
assert length() != 0 : "Queue is empty";
return listArray[rear];
}
#Override
public boolean isEmpty() {
if(listArray == null){
return true;
}
return false;
}
/**
* #return Queue length
**/
public int length() {
return ((rear + maxSize) - front + 1) % maxSize;
}
}
I've been scratching my head over this for days, so any help would be incredibly appreciated! Thank you!

The issue is that your isEmpty() method doesn't work the way you want it to. You are using it as if it checks whether there is anything in the queue, but it is written to do something else. Assuming your length() method is correct, you need to check whether length() == 0. If it does, then you should return true. If not, you should return false.
The reason you are getting a NullPointerException is because you are assuming your list isn't empty when it is, so you try to access the next thing in your queue, which is null
In code, it would look like this:
public boolean isEmpty() {
return length()==0;
}

I don't have your driver class, so I made do with what's available:
public static void main(String [] args) {
ArrayDeque<Integer> runway1 = new ArrayDeque<>();
ArrayDeque<Integer> runway2 = new ArrayDeque<>();
//adds 7 planes into runway 1
for (int i = 0; i < 7; i++) {
runway1.offer(i);
}
//adds 4 planes into runway 2
for (int i = 0; i < 4; i++) {
runway2.offer(i);
}
//run loop while either runway has planes left
String waitingMsg = "There are currently %d planes waiting for takeoff in Runway %d.";
while (!runway1.isEmpty() && !runway2.isEmpty()) {
System.out.println(String.format(waitingMsg, runway1.size(), 1));
System.out.println(String.format(waitingMsg, runway2.size(), 2));
System.out.println();
for (int lane = 0; lane < 7; lane++) {
if (runway1.isEmpty()){
System.out.println("Runway 1 is empty.");
} else {
int lane1 = runway1.pop();
System.out.println("Plane " + lane1 + " has taken off from Runway 1.");
}
if (runway2.isEmpty()) {
System.out.println("Runway 2 is empty.");
} else{
int lane2 = runway2.pop();
System.out.println("Plane " + lane2 + " has taken off from Runway 2.\n");
}
}
}
}

Related

I have some problems with ArrayList (quiz of head first java)

I've just started learning java since last week. I'm using book called 'head first java' and i'm struggling with solving problems about ArrayList. Error says "The method setLocationCells(ArrayList) in the type DotCom is not applicable for the
arguments (int[])" and I haven't found the solution :( help me..!
enter image description here
This looks like a Locate & Conquer type game similar to the game named Battleship with the exception that this game is a single player game played with a single hidden ship in a single horizontal row of columnar characters. Rather simplistic but kind of fun to play I suppose. The hard part is to locate the hidden ship but once you've located it, conquering (sinking) it becomes relatively easy. I'm sure this isn't the games' intent since it is after all named "The Dot Com Game" but the analogy could be possibly helpful.
There are several issues with your code but there are two major ones that just can not be there for the game to work:
Issue #1: The call to the DotCom.setLocationCells() method:
The initial problem is located within the DotComGame class on code line 13 (as the Exception indicates) where the call is made to the DotCom.setLocationCells() method. As already mentioned in comments the wrong parameter type is passed to this method. You can not pass an int[] Array to the setLocationCell() method when this method contains a parameter signature that stipulates it requires an ArrayList object. The best solution in my opinion would be to satisfy the setLocationCells() method parameter requirement...supply an ArrayList to this method.
The reason I say this is because all methods within the DotCom class work with an established ArrayList and one of the tasks of one of these methods (the checkYourself() method) actually removes elements from the ArrayList which is easy to do from a collection but very cumbersome to do the same from an Array.
To fix this problem you will need to change the data type for the locations variable located within the DotComGame class. Instead of using:
int[] locations = {randomNum, randomNum + 1, randomNum + 2};
you should have:
ArrayList<Integer> locations = new ArrayList<>(
Arrays.asList(random, randomNum + 1, randomNum + 2));
or you could do it this way:
ArrayList<Integer> locations = new ArrayList<>();
locations.add(randomNum);
locations.add(randomNum + 1);
locations.add(randomNum + 2);
There are other ways but these will do for now. Now, when the call to the setLocationCells() method is made you ahouldn't get an exception this issue should now be resolved.
Issue #2: The call to the DotCom.checkYourself() method:
Again, this particular issue is located within the DotComGame class on code line 18 where the call is made to the DotCom.checkYourself() method. Yet another parameter data type mismatch. You are trying to pass a variable of type String (named guess) to this method whereas its signature stipulates that it requires an integer (int) value. That again is a no go.
To fix this problem you will need to convert the string numerical value held by the guess variable to an Integer (int) value. So instead of having this:
while(isAlive) {
String guess = helper.getUserInput("Enter a Number: ");
String result = theDotCom.checkYourself(guess);
// ... The rest of your while loop code ...
}
you should have something like:
while(isAlive) {
String guess = helper.getUserInput("Enter a Number: ");
/* Validate. Ensure guess holds a string representation
of a Integer numerical value. */
if (!guess.matches("\\d+")) {
System.err.println("Invalid Value (" + guess
+ ") Supplied! Try again...");
continue;
}
int guessNum = Integer.parseInt(guess);
String result = theDotCom.checkYourself(guessNum);
numOfGuesses++;
if (result.equals("kill")) {
isAlive = false;
System.out.println(numOfGuesses + " guesses!");
}
else if (result.equals("hit")) {
// Do Something If You Like
System.out.println("HIT!");
}
else {
System.out.println("Missed!");
}
}
Below is a game named Simple Battleship which I based off of your code images (please don't use images for code anymore - I hate using online OCR's ;)
BattleshipGame.java - The application start class:
import java.awt.Toolkit;
public class BattleshipGame {
public static int gameLineLength = 10;
public static void main(String[] args) {
GameHelper helper = new GameHelper();
Battleship theDotCom = new Battleship();
int score = 0; // For keeping an overall score
// Display About the game...
System.out.println("Simple Battleship Game");
System.out.println("======================");
System.out.println("In this game you will be displayed a line of dashes.");
System.out.println("Each dash has the potential to hide a section of a");
System.out.println("hidden Battleship. The size of this ship is randomly");
System.out.println("chosen by the game engine and can be from 1 to 5 sections");
System.out.println("(characters) in length. The score for each battle is based");
System.out.println("on the length of the game line that will be displayed to");
System.out.println("you (default is a minimum of 10 charaters). You now have");
System.out.println("the option to supply the game line length you want to play");
System.out.println("with. If you want to use the default then just hit ENTER:");
System.out.println();
// Get the desire game line length
String length = helper.getUserInput("Desired Game Line Length: --> ", "Integer", true, 10, 10000);
if (!length.isEmpty()) {
gameLineLength = Integer.parseInt(length);
}
System.out.println();
// Loop to allow for continuous play...
boolean alwaysReplay = true;
while (alwaysReplay) {
int numOfGuesses = 0;
/* Create a random ship size to hide within the line.
It could be a size from 1 to 5 characters in length. */
int shipSize = new java.util.Random().nextInt((5 - 1) + 1) + 1;
int randomNum = (int) (Math.random() * (gameLineLength - (shipSize - 1)));
int[] locations = new int[shipSize];
for (int i = 0; i < locations.length; i++) {
locations[i] = randomNum + i;
}
System.out.println("Destroy the " + shipSize + " character ship hidden in the");
System.out.println("displayed line below:");
System.out.println();
String gameLine = String.join("", java.util.Collections.nCopies(gameLineLength, "-"));
theDotCom.setLocationCells(locations);
// Play current round...
boolean isAlive = true;
while (isAlive == true) {
System.out.println(gameLine);
String guess = helper.getUserInput("Enter a number from 1 to " + gameLineLength
+ " (0 to quit): --> ", "Integer", 1, gameLineLength);
int idx = Integer.parseInt(guess);
if (idx == 0) {
System.out.println("Quiting with an overall score of: " + score + " ... Bye-Bye");
alwaysReplay = false;
break;
}
idx = idx - 1;
String result = theDotCom.checkYourself(idx);
numOfGuesses++;
System.out.println(result);
if (result.equalsIgnoreCase("kill")) {
Toolkit.getDefaultToolkit().beep();
isAlive = false;
/* Tally the score dependent upon the gameLineLength... */
if (gameLineLength <= 10) { score += 5; }
else if (gameLineLength > 10 && gameLineLength <= 20) { score += 10; }
else if (gameLineLength > 20 && gameLineLength <= 30) { score += 15; }
else if (gameLineLength > 30 && gameLineLength <= 40) { score += 20; }
else { score += 25; }
gameLine = gameLine.substring(0, idx) + "x" + gameLine.substring(idx + 1);
System.out.println(gameLine);
System.out.println(numOfGuesses + " guesses were made to sink the hidden ship.");
System.out.println("Your overall score is: " + (score < 0 ? 0 : score));
}
else if (result.equalsIgnoreCase("hit")) {
gameLine = gameLine.substring(0, idx) + "x" + gameLine.substring(idx + 1);
}
if (result.equalsIgnoreCase("miss")) {
score -= 1;
}
System.out.println();
}
// Play Again? [but only if 'alwaysReplay' holds true]
if (alwaysReplay) {
String res = helper.getAnything("<< Press ENTER to play again >>\n"
+ "<< or enter 'q' to quit >>");
if (res.equalsIgnoreCase("q")) {
System.out.println("Quiting with an overall score of: " + score + " ... Bye-Bye");
break;
}
System.out.println();
}
}
}
}
GameHelper.java - The GameHelper class:
import java.util.Scanner;
public class GameHelper {
private final Scanner in = new Scanner(System.in);
public String getUserInput(String prompt, String responseType, int... minMAX) {
int min = 0, max = 0;
if (minMAX.length == 2) {
min = minMAX[0];
max = minMAX[1];
}
if (minMAX.length > 0 && min < 1 || max < 1) {
throw new IllegalArgumentException("\n\ngetUserInput() Method Error! "
+ "The optional parameters 'min' and or 'max' can not be 0!\n\n");
}
String response = "";
while (response.isEmpty()) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
response = in.nextLine().trim();
if (responseType.matches("(?i)\\b(int|integer|float|double)\\b")) {
if (!response.matches("-?\\d+(\\.\\d+)?") ||
(responseType.toLowerCase().startsWith("int") && response.contains("."))) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
continue;
}
}
// Check entry range value if the entry is to be an Integer
if (responseType.toLowerCase().startsWith("int")) {
int i = Integer.parseInt(response);
if (i != 0 && (i < min || i > max)) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
}
}
}
return response;
}
public String getUserInput(String prompt, String responseType, boolean allowNothing, int... minMAX) {
int min = 0, max = 0;
if (minMAX.length == 2) {
min = minMAX[0];
max = minMAX[1];
}
if (minMAX.length > 0 && min < 1 || max < 1) {
throw new IllegalArgumentException("\n\ngetUserInput() Method Error! "
+ "The optional parameters 'min' and or 'max' can not be 0!\n\n");
}
String response = "";
while (response.isEmpty()) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
response = in.nextLine().trim();
if (response.isEmpty() && allowNothing) {
return "";
}
if (responseType.matches("(?i)\\b(int|integer|float|double)\\b")) {
if (!response.matches("-?\\d+(\\.\\d+)?") ||
(responseType.toLowerCase().startsWith("int") && response.contains("."))) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
continue;
}
}
// Check entry range value if the entry is to be an Integer
if (responseType.toLowerCase().startsWith("int")) {
int i = Integer.parseInt(response);
if (i != 0 && (i < min || i > max)) {
System.err.println("Invalid Entry (" + response + ")! Try again...");
response = "";
}
}
}
return response;
}
public String getAnything(String prompt) {
if (prompt.trim().endsWith("-->")) {
System.out.print(prompt);
}
else {
System.out.println(prompt);
}
return in.nextLine().trim();
}
}
Battleship.java - The Battleship class:
import java.util.ArrayList;
public class Battleship {
private ArrayList<Integer> locationCells;
public void setLocationCells(java.util.ArrayList<Integer> loc) {
locationCells = loc;
}
// Overload Method (Java8+)
public void setLocationCells(int[] loc) {
locationCells = java.util.stream.IntStream.of(loc)
.boxed()
.collect(java.util.stream.Collectors
.toCollection(java.util.ArrayList::new));
}
/*
// Overload Method (Before Java8)
public void setLocationCells(int[] loc) {
// Clear the ArrayList in case it was previously loaded.
locationCells.clear();
// Fill the ArrayList with integer elements from the loc int[] Array
for (int i = 0; i < loc.length; i++) {
locationCells.add(loc[i]);
}
}
*/
/**
* Completely removes one supplied Integer value from all elements
* within the supplied Integer Array if it exist.<br><br>
*
* <b>Example Usage:</b><pre>
*
* {#code int[] a = {103, 104, 100, 10023, 10, 140, 2065};
* a = removeFromArray(a, 104);
* System.out.println(Arrays.toString(a);
*
* // Output will be: [103, 100, 10023, 10, 140, 2065]}</pre>
*
* #param srcArray (Integer Array) The Integer Array to remove elemental
* Integers from.<br>
*
* #param intToDelete (int) The Integer to remove from elements within the
* supplied Integer Array.<br>
*
* #return A Integer Array with the desired elemental Integers removed.
*/
public static int[] removeFromArray(int[] srcArray, int intToDelete) {
int[] arr = {};
int cnt = 0;
boolean deleteIt = false;
for (int i = 0; i < srcArray.length; i++) {
if (srcArray[i] != intToDelete) {
arr[cnt] = srcArray[i];
cnt++;
}
}
return arr;
}
public String checkYourself(int userInput) {
String result = "MISS";
int index = locationCells.indexOf(userInput);
if (index >= 0) {
locationCells.remove(index);
if (locationCells.isEmpty()) {
result = "KILL";
}
else {
result = "HIT";
}
}
return result;
}
}

Turning a Queue into a Priority Queue

In the CarWash program that I have right now there is currently a normal queue that I would like to change into a priority queue. My goal is to take one of the basic server characteristics and use that for priority but I am lost on how to do that. In previous attempts I have tried to change the normal queue into a priority queue and have ran into issues on how I am supposed to base it off a server characteristic.
public class CarWash {
public static void main(String[ ] args) {
Scanner kb = new Scanner (System.in);
System.out.println("Enter wash time: ");
int WASHTIME = kb.nextInt();
System.out.println("Enter arrival probability: ");
double ARRIVALPROB = kb.nextDouble();
System.out.println("enter time for simulation: ");
int TOTALTIME = kb.nextInt();
carWashSimulate(WASHTIME, ARRIVALPROB, TOTALTIME);
}
public static void carWashSimulate(int washTime, double arrivalProb, int totalTime) { //simulates the car wash
Queue<Integer> arrivalTimes = new LinkedList<Integer>( );
int next;
ClientGenerator arrival = new ClientGenerator(arrivalProb);
Server machine = new Server(washTime);
ExpressServer newM = new ExpressServer(washTime);
Averager waitTimes = new Averager( );
Averager lostCustomer = new Averager();
int currentSecond;
// Write the parameters to System.out.
System.out.println("Seconds to wash one car: " + washTime);
System.out.print("Probability of customer arrival during a second: ");
System.out.println(arrivalProb);
System.out.println("Total simulation seconds: " + totalTime);
// Check the precondition:
if (washTime <= 0 || arrivalProb < 0 || arrivalProb > 1 || totalTime < 0)
throw new IllegalArgumentException("Values out of range");
for (currentSecond = 0; currentSecond < totalTime; currentSecond++) {
// Simulate the passage of one second of time
// Check whether a new customer has arrived.
if (arrival.query( )){
System.out.println("Customer arrived at " + currentSecond);
if(arrivalTimes.size() <= 8){
arrivalTimes.add(currentSecond);
}
else{
System.out.println("They left, line was too long");
lostCustomer.addNumber(1);
}
// Check whether we can start washing another car.
if ((!machine.isBusy( )) && (!arrivalTimes.isEmpty( )))
{
next = arrivalTimes.remove( );
waitTimes.addNumber(currentSecond - next);
machine.start( );
System.out.println("Server started at " + currentSecond + " serving customer " + next);
}
// Subtract one second from the remaining time in the current wash cycle.
machine.reduceRemainingTime( );
} // end of for loop
// Write the summary information about the simulation.
System.out.println("Customers served: " + waitTimes.howManyNumbers( ));
if (waitTimes.howManyNumbers( ) > 0)
System.out.println("Average wait for customers served: " + waitTimes.average( ) + " sec");
System.out.println("The number of customers lost was " + lostCustomer);
}
}
}
Client Generator Class:
public class ClientGenerator {
private double probability;
// The approximate probability of query( ) returning true.
public ClientGenerator(double p) {
if ((p < 0) || (1 < p))
throw new IllegalArgumentException("Illegal p: " + p);
probability = p;
}
public void adjust(double a) {
if(a > 0 && a+probability < 1) {
probability = probability + a;
} else if (a < 0 && probability + a > 0) {
probability = probability + a;
}
}
public double getProbability() {
return probability;
}
public boolean query( ) {
return (Math.random( ) < probability);
}
}
Server Class:
public class Server {
private int secondsForService; // Seconds for a single wash
private int timeLeft; // Seconds until this Server is no longer busy
public Server(int s) {
secondsForService = s;
timeLeft =0;
}
public boolean isBusy( ) {
return (timeLeft > 0);
}
public void reduceRemainingTime( ) {
if (timeLeft > 0) timeLeft--;
}
public void start( ) {
if (timeLeft > 0)
throw new IllegalStateException("Server is already busy.");
timeLeft = secondsForService;
}
}
Averager class:
public class Averager
{
private int count; // How many numbers have been given to this averager
private double sum; // Sum of all the numbers given to this averager
public Averager( )
{
count =0;
sum = 0;
}
public void addNumber(double value)
{
if (count == Integer.MAX_VALUE)
throw new IllegalStateException("Too many numbers");
count++;
sum += value;
}
public double average( )
{
if (count == 0)
return Double.NaN;
else
return sum/count;
}
public int howManyNumbers( )
{
return count;
}
}
The question seems to be about how to configure the priority rules employed by a java.util.PriorityQueue. That's relatively straightforward. Depending on which constructor you use to instantiate one, PriorityQueue relies either on the natural order of its elements (see Comparable) or on the order defined by a specified Comparator. Whenever such a queue contains any elements, its head is the least with respect to the operative ordering, or among the least if there are multiple elements such that no other element is less.
In comments you clarified
my goal is to implement some way of randomly assigning a value that represents the type of car, which will then prioritize the luxury car before the other cars.
Note well that PriorityQueue uses the properties of the enqueued objects to establish their relative order. Right now you are enqueuing integer arrival times, which don't confer an ability to distinguish between classes of car. If you want to carry more information about each vehicle that arrives then you would probably want to create a new class for that, maybe something like this:
class ClientArrival {
enum Category { NORMAL, LUXURY }
Category category;
int arrivalTime;
// ...
}
You would then be able to create one or more implementations of Comparator<ClientArrival> to use to define the priority rule for a PriorityQueue<ClientArrival>. For example,
class LuxuryFirstComparator implements Comparator<ClientArrival> {
int compare(ClientArrival o1, ClientArrival o2) {
if (o1.getCategory() == o2.getCategory()) {
// ... order based on arrival time ...
} else if (o1.getCategory() == ClientArrival.Category.LUXURY) {
return -1;
} else {
return 1;
}
}
}
One might set up a PriorityQueue<ClientArrival> using that to determine priority via
Queue<ClientArrival> arrivals = new PriorityQueue<>(new LuxuryFirstComparator());

Java monitors and thread concurrency

I'm trying to build simple multithreading application. But I'm confused about Java monitors. I have many threads that want to format with their data one array. So for example I have Supermarket Threads (data of the thread is in txt file) So first thread have these product (Milk, Cheese, Chocolate) and country code for each product 1,2, 3
SupermarketA
Milk 1
Cheese 2
Chocolate 3
SupermarketB
Yogurt 1
Orangle 2
Bannana 3
Tea 7
Kiwi 9
and I want to format array that has to fields (country_code and count)
So my array should look like that
Country_code count
1 2
2 2
3 2
7 1
9 1
Code
public class SortedArray{
private int num = 0; // num is country code
private int count = 0;
}
So here's my monitor class
public class SingleArray {
private SortedArray[] array;
private int arrayIndex;
private static final int MAX_SIZE = 5;
public SingleArray() {
array = new SortedArray[MAX_SIZE];
arrayIndex = 0;
initArray();
}
private void initArray() {
for (int i = 0; i < MAX_SIZE; i++) {
array[i] = new SortedArray();
}
}
public synchronized void inc(){
awaitUnderMax();
notifyAll();
}
private void awaitUnderMin(){
while (arrayIndex == 0) try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void dec(){
awaitUnderMin();
notifyAll();
}
public void add(ArrayList<Integer> count){
for (int i = 0; i < count.size(); i++) {
singleArray.inc();
int num = count.get(i);
if (singleArray.arrayIndex == 0) { // if array is empty add value to it
singleArray.array[0].num = num;
singleArray.array[0].count++;
singleArray.arrayIndex++;
} else {
if (!isThere(num)) { // if num is a new value to array
singleArray.inc();
int index1 = singleArray.arrayIndex;
if (num > singleArray.array[index1 - 1].num) {
singleArray.inc();
singleArray.array[index1].num = num;
singleArray.inc();
singleArray.array[index1].count++;
singleArray.inc();
singleArray.arrayIndex++;
System.out.println(Thread.currentThread().getName() + " first " + singleArray.array[index1].num);
} else if (num < singleArray.array[index1 - 1].num) { // jei num mazesne uz paskutinia masyvo reiksme
int index = index1 - 1 < 0 ? index1 : index1 - 1;
while (index > 0 && num < singleArray.array[index].num) {
index--;
}
if (index != singleArray.arrayIndex) {
System.out.println(Thread.currentThread().getName() + " sec " + singleArray.array[index].num);
singleArray.array = addPos(singleArray.array, index + 1, num);
}
}
}
}
}
}
public boolean isThere(int number){
for(int i=0; i<singleArray.arrayIndex; i++){
singleArray.inc();
if(number == singleArray.array[i].num){
singleArray.array[i].count++;
return true;
}
}
return false;
}
private void awaitUnderMax(){
while (arrayIndex >= MAX_SIZE) try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void removeValue(int number, int howManyItems){
for(int i=0; i<arrayIndex; i++){
dec();
if(number == array[i].num){
int numberToDelete = array[i].count - howManyItems >= 0 ? howManyItems : array[i].count;
if(array[i].count >= numberToDelete){
array[i].count -= numberToDelete;
}
if(array[i].count == 0){
deleteItem(i);
}
}
if(array[i].count == 0){
deleteItem(i);
}
}
}
Each thread call add(ArrayList<Integer> count) method
So basically what add method does:
Find place where to insert new value (dependng if new value is greater or lower than a previous)
call isThere(int num) method that check if new value is already in array (if so increment count singleArray.array[i].count++) otherwise add new value to array
If array is full arrayIndex == MAX_SIZE wait current thread for other threads to decrement arrayIndex (this is oly one part of code I also have other threads that based on county code decrement array)
So the biggest problem is that multiplethreads need to update single array at the same time (I know that adding synchronized keyword to add method should solve this problem but it only let one thread to run this method at once!) So sometimes all works fine, but sometimes I get really starnge results (for example that country code is 0 (That is imposible!!!) and sometimes new values is placed in wrong array posiitons). Also I think that semaphores should solve this problem, but is it possible to do that with monitors? Thank's for the answers.
EDIT v2
to #Elyasin
public Thread[] setUpShopsBuilderThreads(){
int size = data.getSize();
ArrayList<ArrayList<String>> a = new ArrayList<>();
ArrayList<ArrayList<Integer>> b = new ArrayList<>();
ArrayList<ArrayList<Double>> c = new ArrayList<>();
Thread[] threads = new Thread[size];
for (int i = 0; i < size; i++) {
int tmp = data.getIndex(i);
int range = i + 1 < size ? data.getIndex(i + 1) : data.getWaresSize();
ArrayList<String> name = new ArrayList<>();
ArrayList<Integer> count = new ArrayList<>();
ArrayList<Double> price = new ArrayList<>();
for (int j = tmp; j < range; j++) {
name.add(data.getName(j));
count.add(data.getCount(j));
price.add(data.getPrice(j));
}
a.add(name);
b.add(count);
c.add(price);
}
procesas_1 p1 = new procesas_1(a.get(0), b.get(0), c.get(0));
procesas_2 p2 = new procesas_2(a.get(1), b.get(1), c.get(1));
procesas_3 p3 = new procesas_3(a.get(2), b.get(2), c.get(2));
procesas_4 p4 = new procesas_4(a.get(3), b.get(3), c.get(3));
procesas_5 p5 = new procesas_5(a.get(4), b.get(4), c.get(4));
Thread worker1 = new Thread(p1);
Thread worker2 = new Thread(p2);
Thread worker3 = new Thread(p3);
Thread worker4 = new Thread(p4);
Thread worker5 = new Thread(p5);
threads[0] = worker1;
threads[1] = worker2;
threads[2] = worker3;
threads[3] = worker4;
threads[4] = worker5;
return threads;
}
public static void main(String[] args) {
Starter start = new Starter();
start.read();
start.printShopsData();
start.printUserData();
Thread[] builderThreads = start.setUpShopsBuilderThreads();
for(int i=0; i<builderThreads.length; i++){
builderThreads[i].start();
}
}
what about using the concurrent safe datasets java already provides?
if you want it sorted, this one looks it might work for you:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListSet.html
just add it as in a normal Collection

Printing randomly fed values from an ArrayList in Java

I am processing elements of an ArrayList in random order, generally by printing them out. I would like to detect when the randomly selected index is 0 or 1 so as to perform special handling for those cases, where the handling for index 0 is partially dependent on whether index 1 has previously been processed. Specifically, nothing is immediately printed when index 1 is processed, but if it is processed then when index 0 is subsequently processed, both the index 1 and the index 0 values are printed. In any event, the loop is exited after ten iterations or after processing index 0, whichever comes first.
I tried to implement this using if statements, but there where obvious flaws with that one. I have searched everywhere for any examples but found none. I have begun to consider using sorting algorithms or threads to hold the first value found then continue looping until it sees the second the print it out. I would appreciate any help possible.
Here is my code:
public static void random_sortType(){
types = new ArrayList<String>();
types.add("Start");
types.add("Starting");
types.add("Load");
types.add("Loading");
types.add("End");
ran = new Random();
int listSize = types.size();
String tempEventType;//the temp variable intended to hold temporary values
for(int i = 0; i < 10; i++){ //the loop goes round the ArrayList 10 times
int index = ran.nextInt(listSize);//this produces the random selection of the elements within the list
if(index == 0){
out.println(types.get(index));
out.println();
break;
}
if(index == 1){
tempEventType = types.get(index);
if(index == 0){
tempEventType = types.get(0) + " " + types.get(1);
out.println(tempEventType);
break;
}
}/*if(index == 0){
tempEventType = types.get(0) + " " + types.get(1);
out.println(tempEventType);
break;
}*/
//out.print("Index is " + index + ": ");
//out.println(types.get(index));
}
}
You need to store the random generated index into a global variable and update it everytime a random number is generated. It should be something like this.
public static void random_sortType(){
types = new ArrayList<String>();
types.add("Start");
types.add("Starting");
types.add("Load");
types.add("Loading");
types.add("End");
` int previousIndex;
ran = new Random();
int listSize = types.size();
String tempEventType;//the temp variable intended to hold temporary values
for(int i = 0; i < 10; i++){ //the loop goes round the ArrayList 10 times
int index = ran.nextInt(listSize);//this produces the random selection of the elements within the list
previous_index =index;
if(index == 0){
out.println(types.get(index));
out.println();
break;
}
if(index == 1){
tempEventType = types.get(index);
if(previousIndex == 0){
temp EventType = types.get(0) + " " + types.get(1);
out.println(tempEventType);
break;
}
According to your description, these are the basic requirements for your application:
Process ArrayList in random order
Processing = printing value at randomly selected index
Make 10 attempts to process items in the list.
Detect when random index is 1 or 0.
if 1
don't process, but flag it was selected.
if 0 && 1 is flagged
process 0 and 1
exit
If these requirements are correct, here is the implementation I came up with:
import java.util.ArrayList;
import java.util.Random;
import static java.lang.System.*;
public class RandomSort {
private static final int MAX_ATTEMPTS = 10;
private static boolean wasOneSelected = false;
public static void main(String[] args) {
ArrayList<String> types = new ArrayList<>(5);
types.add("Start");
types.add("Starting");
types.add("Load");
types.add("Loading");
types.add("End");
random_sortType(types);
}
public static void random_sortType(ArrayList<String> types) {
Random ran = new Random();
int lastIndex = types.size() - 1; // index range is from 0 to 4
for (int i = 0; i < MAX_ATTEMPTS; i++) {
int index = ran.nextInt(lastIndex);
if ( (index == 0) && wasOneSelected) {
process(types.get(index) + " " + types.get(index + 1));
break;
} else if (index == 1) {
wasOneSelected = true;
} else {
process(types.get(index));
}
}
}
public static void process(String str) {
out.println("Processing: " + str);
}
}
The key here is the inclusion of the boolean wasOneSelected initialized to false. Once it is set to true, it will never be false again for the duration of the application. The if-else block handles all branching within the loop, and I favored wrapping the println call into a method called "process" for readability purposes to align it more closely with your description.
Feedback appreciated :)

Making change recursively: How do I modify my algorithm to print all combinations?

I have an algorithm that recursively makes change in the following manner:
public static int makeChange(int amount, int currentCoin) {
//if amount = zero, we are at the bottom of a successful recursion
if (amount == 0){
//return 1 to add this successful solution
return 1;
//check to see if we went too far
}else if(amount < 0){
//don't count this try if we went too far
return 0;
//if we have exhausted our list of coin values
}else if(currentCoin < 0){
return 0;
}else{
int firstWay = makeChange(amount, currentCoin-1);
int secondWay = makeChange(amount - availableCoins[currentCoin], currentCoin);
return firstWay + secondWay;
}
}
However, I'd like to add the capability to store or print each combination as they successfully return. I'm having a bit of a hard time wrapping my head around how to do this. The original algorithm was pretty easy, but now I am frustrated. Any suggestions?
CB
Without getting into the specifics of your code, one pattern is to carry a mutable container for your results in the arguments
public static int makeChange(int amount, int currentCoin, List<Integer>results) {
// ....
if (valid_result) {
results.add(result);
makeChange(...);
}
// ....
}
And call the function like this
List<Integer> results = new LinkedList<Integer>();
makeChange(amount, currentCoin, results);
// after makeChange has executed your results are saved in the variable "results"
I don't understand logic or purpose of above code but this is how you can have each combination stored and then printed.
public class MakeChange {
private static int[] availableCoins = {
1, 2, 5, 10, 20, 25, 50, 100 };
public static void main(String[] args) {
Collection<CombinationResult> results = makeChange(5, 7);
for (CombinationResult r : results) {
System.out.println(
"firstWay=" + r.getFirstWay() + " : secondWay="
+ r.getSecondWay() + " --- Sum=" + r.getSum());
}
}
public static class CombinationResult {
int firstWay;
int secondWay;
CombinationResult(int firstWay, int secondWay) {
this.firstWay = firstWay;
this.secondWay = secondWay;
}
public int getFirstWay() {
return this.firstWay;
}
public int getSecondWay() {
return this.secondWay;
}
public int getSum() {
return this.firstWay + this.secondWay;
}
public boolean equals(Object o) {
boolean flag = false;
if (o instanceof CombinationResult) {
CombinationResult r = (CombinationResult) o;
flag = this.firstWay == r.firstWay
&& this.secondWay == r.secondWay;
}
return flag;
}
public int hashCode() {
return this.firstWay + this.secondWay;
}
}
public static Collection<CombinationResult> makeChange(
int amount, int currentCoin) {
Collection<CombinationResult> results =
new ArrayList<CombinationResult>();
makeChange(amount, currentCoin, results);
return results;
}
public static int makeChange(int amount, int currentCoin,
Collection<CombinationResult> results) {
// if amount = zero, we are at the bottom of a successful recursion
if (amount == 0) {
// return 1 to add this successful solution
return 1;
// check to see if we went too far
} else if (amount < 0) {
// don't count this try if we went too far
return 0;
// if we have exhausted our list of coin values
} else if (currentCoin < 0) {
return 0;
} else {
int firstWay = makeChange(
amount, currentCoin - 1, results);
int secondWay = makeChange(
amount - availableCoins[currentCoin],
currentCoin, results);
CombinationResult resultEntry = new CombinationResult(
firstWay, secondWay);
results.add(resultEntry);
return firstWay + secondWay;
}
}
}
I used the following:
/**
* This is a recursive method that calculates and displays the combinations of the coins included in
* coinAmounts that sum to amountToBeChanged.
*
* #param coinsUsed is a list of each coin used so far in the total. If this branch is successful, we will add another coin on it.
* #param largestCoinUsed is used in the recursion to indicate at which coin we should start trying to add additional ones.
* #param amountSoFar is used in the recursion to indicate what sum we are currently at.
* #param amountToChange is the original amount that we are making change for.
* #return the number of successful attempts that this branch has calculated.
*/private static int change(List<Integer> coinsUsed, Integer currentCoin, Integer amountSoFar, Integer amountToChange)
{
//if last added coin took us to the correct sum, we have a winner!
if (amountSoFar == amountToChange)
{
//output
System.out.print("Change for "+amountToChange+" = ");
//run through the list of coins that we have and display each.
for(Integer count: coinsUsed){
System.out.print(count + " ");
}
System.out.println();
//pass this back to be tallied
return 1;
}
/*
* Check to see if we overshot the amountToBeChanged
*/
if (amountSoFar > amountToChange)
{
//this branch was unsuccessful
return 0;
}
//this holds the sum of the branches that we send below it
int successes=0;
// Pass through each coin to be used
for (Integer coin:coinAmounts)
{
//we only want to work on currentCoin and the coins after it
if (coin >= currentCoin)
{
//copy the list so we can branch from it
List<Integer> copyOfCoinsUsed = new ArrayList<Integer>(coinsUsed);
//add on one of our current coins
copyOfCoinsUsed.add(coin);
//branch and then collect successful attempts
successes += change(copyOfCoinsUsed, coin, amountSoFar + coin, amountToChange);
}
}
//pass back the current
return successes;
}

Categories

Resources