I have created an arrayList treat to show 5 instances of a treatment room, I have also created a linkedList inTreatment for the treatment room to pass 5 patient objects into from queue, however when I pass multiple objects to the linkedList they constantly replace the first element added instead of moving to the next element available. I believe the problem lies with the inTreatment.add line but i'm not sure how to reference the next available index. All suggestions are more than welcome.
Below is my code for creating the array and adding to the inTreatment linkedList.
Creating treatment rooms array
public static void createTreatmentRooms() {
for (int i = 0; i < treat.length; i++) {
treat[i] = new TreatmentRoom();
treat[i].setAvailable(true);
}
}
Add to treatment rooms method
for (int i = 0; i < TreatmentRoom.treat.length; i++) {
if ((TreatmentRoom.treat[i].isAvailable())
&& (Queue.queue.size() != 0)
&& (Queue.queue.getFirst().getTriage() != Status.NOT_ASSESSED)) {
// add patient to inTreatment list for future sorting...
inTreatment.add(queue.getFirst());
System.out.println("taken to treatment queue");
// remove patient from front of queue
for (Patient p : queue) {
System.out.println(p.getFirstName());
}
queue.poll();
System.out.println("second queue");
for (Patient p : queue) {
System.out.println(p.getFirstName());
}
System.out.println("removed from queue");
// if free, add patient to treatment room
TreatmentRoom.treat[i].setPatient(inTreatment.getFirst());
System.out.println("sent to treatment room"
+ TreatmentRoom.treat[i]);
// System.out.println("patient added" +
// queue.get(i).getFirstName());
// set treatment room to unavailable
TreatmentRoom.treat[i].setAvailable(false);
System.out.println("treatment room busy");
} else {
System.out.println("Treatment room is not available");
}
}
}
The problem might come from here:
queue.remove(i);
You're removing the element at index i, but that i is in the range of the rooms, and has nothing to do with the queue, does it?
You might want to remove the first element instead.
Side note: there should be a poll() method that allows you to peek and remove the first element of your queue in one call by the way, but I'm unusure what type of queue you're using here, it does not look like java.util.Queue.
Related
In a piece of code I'm currently working on, I'm taking in an ArrayList of data to be added to an object, from a user. I'm checking each item in the ArrayList against the current list of that type of data for the object, in order to make sure it's not in the list already.
Is there a way to throw an exception for one item in the passed- in list, to tell the user it's in the list already- and then to keep going and add the next items in the passed-in list to my current list if they aren't there already?
Update: i solved the problem by surrounding that block of code with a try/catch. Here's my code to clarify:
public void addCategories(ArrayList<BookCategory>categories) {
boolean exists;
for(int index = 0; index <categories.size(); index++) {//iterate through passed array list
try {
//for each element, check if it exists in the current category list.
exists = checkBookCategory(categories.get(index));
if (exists == false)
{subjectCategories.add(categories.get(index));}
else {
throw new IllegalArgumentException("Item " + categories.get(index) + " already in list."); }
}catch(IllegalArgumentException ie) {
System.out.println(ie);
} }
}
Thanks #JimGarrison!
The short answer is that yes, you can do this, but it usually is highly discouraged.
Some sample pseudocode:
for (Item i : inputList)
{
try
{
myObject.addItem(i);
}
catch (MyCustomDuplicateItemException ex)
{
// Tell the user there was a duplicate
}
}
However, this is using exceptions for what should be flow control. Ideally you would write the addItem() method to return a boolean value (i.e. true) if the item was successfully added, and the other value (false) if the item was a duplicate and NOT throw an exception.
Okay so i have two ArrayLists. The first arraylist starts from the end and tries to add items from my second, which starts from the beginning. I have to listIterators and the concept is to add items to a list of the first one until a maximum capacity is reached, then i continue the additions of new items to the second item of the first list and so on. The problem is when i try to remove an item from the second list, the list won't be reordered and some items won't be checked. Here's the code:
public void loadFromBeh(ArrayList<Cargo> storage) {
ListIterator<Wagon> waIterator = wagons.listIterator(wagons.size());
ListIterator<Cargo> stIterator = storage.listIterator();
while (waIterator.hasPrevious()) {
Wagon w = waIterator.previous();
while (stIterator.hasNext()) {
Cargo c = stIterator.next();
System.out.println("pr " + w.current_weight);
if (c.weight <= w.max_weight) {
if (w.current_weight == 0) {
w.current_weight = c.weight;
System.out.println("first " + w.current_weight);
stIterator.remove();
} else {
w.current_weight = w.current_weight + c.weight;
System.out.println("new current " + w.current_weight);
if (w.current_weight <= w.max_weight) {
w.cargos.add(c);
stIterator.remove();
System.out.println("ok " + w.current_weight);
}
}
}
}
}
}
The problem with your code is not with remove() but lies in the last if clause
if (w.current_weight <= w.max_weight) {
if this is false, that is there is not enough space in the current wagon for the current cargo, then this not only means that the cargo will not be added to the wagon but also that this particular cargo will not be part of ny wagon at all since the end of the loop will be reached and the next cargo will be fetched instead using hasNext().
At this point I assume it would easily happen to more cargos that they will not fit in the current wagon since it is most likely quite full. Once the end of the stIterator has been reached you get a new wagon to fill using previous() but now stIterator.hasNext() will always return false since your at the end of that iterator so no more wagons will be filled with any cargo.
There are several ways to solve this but one thing I think you should do is to separate responsibilities and let the Wagon class take responsibility for adding a cargo, this will make it simpler to write a working loop in my opinion.
I would suggest an add method in the Wagon class
public boolean add(Cargo cargo) {
if ((cargo.weight > max_weight) || (current_weight + cargo.weight > max_weight)) {
return false;
}
current_weight += cargo.weight
cargos.add(cargo);
return true;
}
I am trying to converting a for loop to functional code. I need to look ahead one value and also look behind one value. Is it possible using streams?
The following code is to convert the Roman text to numeric value.
Not sure if reduce method with two/three arguments can help here.
int previousCharValue = 0;
int total = 0;
for (int i = 0; i < input.length(); i++) {
char current = input.charAt(i);
RomanNumeral romanNum = RomanNumeral.valueOf(Character.toString(current));
if (previousCharValue > 0) {
total += (romanNum.getNumericValue() - previousCharValue);
previousCharValue = 0;
} else {
if (i < input.length() - 1) {
char next = input.charAt(i + 1);
RomanNumeral nextNum = RomanNumeral.valueOf(Character.toString(next));
if (romanNum.getNumericValue() < nextNum.getNumericValue()) {
previousCharValue = romanNum.getNumericValue();
}
}
if (previousCharValue == 0) {
total += romanNum.getNumericValue();
}
}
}
No, this is not possible using streams, at least not easily. The stream API abstracts away from the order in which the elements are processed: the stream might be processed in parallel, or in reverse order. So "the next element" and "previous element" do not exist in the stream abstraction.
You should use the API best suited for the job: stream are excellent if you need to apply some operation to all elements of a collection and you are not interested in the order. If you need to process the elements in a certain order, you have to use iterators or maybe access the list elements through indices.
I haven't see such use case with streams, so I can not say if it is possible or not. But when I need to use streams with index, I choose IntStream#range(0, table.length), and then in lambdas I get the value from this table/list.
For example
int[] arr = {1,2,3,4};
int result = IntStream.range(0, arr.length)
.map(idx->idx>0 ? arr[idx] + arr[idx-1]:arr[idx])
.sum();
By the nature of the stream you don't know the next element unless you read it. Therefore directly obtaining the next element is not possible when processing current element. However since you are reading current element you obiously know what was read before, so to achieve such goal as "accesing previous element" and "accessing next element", you can rely on the history of elements which were already processed.
Following two solutions are possible for your problem:
Get access to previously read elements. This way you know the current element and defined number of previously read elements
Assume that at the moment of stream processing you read next element and that current element was read in previous iteration. In other words you consider previously read element as "current" and currently processed element as next (see below).
Solution 1 - implemenation
First we need a data structure which will allow keeping track of data flowing through the stream. Good choice could be an instance of Queue because queues by their nature allows data flowing through them. We only need to bound the queue to the number of last elements we want to know (that would be 3 elements for your use case). For this we create a "bounded" queue keeping history like this:
public class StreamHistory<T> {
private final int numberOfElementsToRemember;
private LinkedList<T> queue = new LinkedList<T>(); // queue will store at most numberOfElementsToRemember
public StreamHistory(int numberOfElementsToRemember) {
this.numberOfElementsToRemember = numberOfElementsToRemember;
}
public StreamHistory save(T curElem) {
if (queue.size() == numberOfElementsToRemember) {
queue.pollLast(); // remove last to keep only requested number of elements
}
queue.offerFirst(curElem);
return this;
}
public LinkedList<T> getLastElements() {
return queue; // or return immutable copy or immutable view on the queue. Depends on what you want.
}
}
The generic parameter T is the type of actual elements of the stream. Method save returns reference to instance of current StreamHistory for better integration with java Stream api (see below) and it is not really required.
Now the only thing to do is to convert the stream of elements to the stream of instances of StreamHistory (where each next element of the stream will hold last n instances of actual objects going through the stream).
public class StreamHistoryTest {
public static void main(String[] args) {
Stream<Character> charactersStream = IntStream.range(97, 123).mapToObj(code -> (char) code); // original stream
StreamHistory<Character> streamHistory = new StreamHistory<>(3); // instance of StreamHistory which will store last 3 elements
charactersStream.map(character -> streamHistory.save(character)).forEach(history -> {
history.getLastElements().forEach(System.out::print);
System.out.println();
});
}
}
In above example we first create a stream of all letters in alphabet. Than we create instance of StreamHistory which will be pushed to each iteration of map() call on original stream. Via call to map() we convert to stream containing references to our instance of StreamHistory.
Note that each time the data flows through original stream the call to streamHistory.save(character) updates the content of the streamHistory object to reflect current state of the stream.
Finally in each iteration we print last 3 saved characters. The output of this method is following:
a
ba
cba
dcb
edc
fed
gfe
hgf
ihg
jih
kji
lkj
mlk
nml
onm
pon
qpo
rqp
srq
tsr
uts
vut
wvu
xwv
yxw
zyx
Solution 2 - implementation
While solution 1 will in most cases do the job and is fairly easy to follow, there are use cases were the possibility to inspect next element and previous is really convenient. In such scenario we are only interested in three element tuples (pevious, current, next) and having only one element does not matter (for simple example consider following riddle: "given a stream of numbers return a tupple of three subsequent numbers which gives the highest sum"). To solve such use cases we might want to have more convenient api than StreamHistory class.
For this scenario we introduce a new variation of StreamHistory class (which we call StreamNeighbours). The class will allow to inspect the previous and the next element directly. Processing will be done in time "T-1" (that is: the currently processed original element is considered as next element, and previously processed original element is considered to be current element). This way we, in some sense, inspect one element ahead.
The modified class is following:
public class StreamNeighbours<T> {
private LinkedList<T> queue = new LinkedList(); // queue will store one element before current and one after
private boolean threeElementsRead; // at least three items were added - only if we have three items we can inspect "next" and "previous" element
/**
* Allows to handle situation when only one element was read, so technically this instance of StreamNeighbours is not
* yet ready to return next element
*/
public boolean isFirst() {
return queue.size() == 1;
}
/**
* Allows to read first element in case less than tree elements were read, so technically this instance of StreamNeighbours is
* not yet ready to return both next and previous element
* #return
*/
public T getFirst() {
if (isFirst()) {
return queue.getFirst();
} else if (isSecond()) {
return queue.get(1);
} else {
throw new IllegalStateException("Call to getFirst() only possible when one or two elements were added. Call to getCurrent() instead. To inspect the number of elements call to isFirst() or isSecond().");
}
}
/**
* Allows to handle situation when only two element were read, so technically this instance of StreamNeighbours is not
* yet ready to return next element (because we always need 3 elements to have previos and next element)
*/
public boolean isSecond() {
return queue.size() == 2;
}
public T getSecond() {
if (!isSecond()) {
throw new IllegalStateException("Call to getSecond() only possible when one two elements were added. Call to getFirst() or getCurrent() instead.");
}
return queue.getFirst();
}
/**
* Allows to check that this instance of StreamNeighbours is ready to return both next and previous element.
* #return
*/
public boolean areThreeElementsRead() {
return threeElementsRead;
}
public StreamNeighbours<T> addNext(T nextElem) {
if (queue.size() == 3) {
queue.pollLast(); // remove last to keep only three
}
queue.offerFirst(nextElem);
if (!areThreeElementsRead() && queue.size() == 3) {
threeElementsRead = true;
}
return this;
}
public T getCurrent() {
ensureReadyForReading();
return queue.get(1); // current element is always in the middle when three elements were read
}
public T getPrevious() {
if (!isFirst()) {
return queue.getLast();
} else {
throw new IllegalStateException("Unable to read previous element of first element. Call to isFirst() to know if it first element or not.");
}
}
public T getNext() {
ensureReadyForReading();
return queue.getFirst();
}
private void ensureReadyForReading() {
if (!areThreeElementsRead()) {
throw new IllegalStateException("Queue is not threeElementsRead for reading (less than two elements were added). Call to areThreeElementsRead() to know if it's ok to call to getCurrent()");
}
}
}
Now, assuming that three elements were already read, we can directly access current element (which is the element going through the stream at time T-1), we can access next element (which is the element going at the moment through the stream) and previous (which is the element going through the stream at time T-2):
public class StreamTest {
public static void main(String[] args) {
Stream<Character> charactersStream = IntStream.range(97, 123).mapToObj(code -> (char) code);
StreamNeighbours<Character> streamNeighbours = new StreamNeighbours<Character>();
charactersStream.map(character -> streamNeighbours.addNext(character)).forEach(neighbours -> {
// NOTE: if you want to have access the values before instance of StreamNeighbours is ready to serve three elements
// you can use belows methods like isFirst() -> getFirst(), isSecond() -> getSecond()
//
// if (curNeighbours.isFirst()) {
// Character currentChar = curNeighbours.getFirst();
// System.out.println("???" + " " + currentChar + " " + "???");
// } else if (curNeighbours.isSecond()) {
// Character currentChar = curNeighbours.getSecond();
// System.out.println(String.valueOf(curNeighbours.getFirst()) + " " + currentChar + " " + "???");
//
// }
//
// OTHERWISE: you are only interested in tupples consisting of three elements, so three elements needed to be read
if (neighbours.areThreeElementsRead()) {
System.out.println(neighbours.getPrevious() + " " + neighbours.getCurrent() + " " + neighbours.getNext());
}
});
}
}
The output of this is following:
a b c
b c d
c d e
d e f
e f g
f g h
g h i
h i j
i j k
j k l
k l m
l m n
m n o
n o p
o p q
p q r
q r s
r s t
s t u
t u v
u v w
v w x
w x y
x y z
By StreamNeighbours class it is easier to track the previous/next element (because we have method with appropriate names), while in StreamHistory class this is more cumbersome since we need to manually "reverse" the order of the queue to achieve this.
As others stated, it's not feasable, to get next elements from within an iterated Stream.
If IntStream is used as a for loop surrogate, which merely acts as an index iteration provider, it's possible use its range iteration index just like with for; one needs to provide a means of skipping the next element on the next iteration, though, e. g. by means of an external skip var, like this:
AtomicBoolean skip = new AtomicBoolean();
List<String> patterns = IntStream.range(0, ptrnStr.length())
.mapToObj(i -> {
if (skip.get()) {
skip.set(false);
return "";
}
char c = ptrnStr.charAt(i);
if (c == '\\') {
skip.set(true);
return String.valueOf(new char[] { c, ptrnStr.charAt(++i) });
}
return String.valueOf(c);
})
It's not pretty, but it works.
On the other hand, with for, it can be as simple as:
List<String> patterns = new ArrayList();
for (char i=0, c=0; i < ptrnStr.length(); i++) {
c = ptrnStr.charAt(i);
patternList.add(
c != '\\'
? String.valueOf(c)
: String.valueOf(new char[] { c, ptrnStr.charAt(++i) })
);
}
EDIT:
Condensed code and added for example.
I am trying to create a linked list from some unordered raw data (String1...Priority10, String2...IntPriority2, etc) and have had trouble conceptualizing how I can sort write a good method for priority queueing. I need to get the method to enqueue each object, in order, without using a sorting algorithm on the final linked list, or using any LinkedList or PriorityQueue itself.
My enqueue method, nothing hard here:
public class ObjectQueue{
Object front = null; //points to first element of the queue
Object prev = null; //points to last element of the queue
/**
* Creates an object of Object and adds to the class queue
* #param name of object
* #param rank of priority sort
*/
public void enQueue(String name, int rank)
{
Object current = new Object(name, rank); //uses current entry String as name, int as rank
if(isEmpty()) //if empty, add element to front
{
front = current;
}
else //if elements exist, go to end and create new element
{
prev.next = current;
}
prev = current;
And the priority sort and add method I'm having trouble with:
/**
* Adds each object and rank on a ascending rank basis
* #param filename name of data file
* #throws exc in case of missing file
*/
public void addPriority(String filename) throws IOException
{
try
{
File inFile = new File(filename); //inst. file import
Scanner read = new Scanner(inFile); //inst. scanner object
String name1 = read.next(); //scanner reads next string, primes at front
int rank1 = read.nextInt(); //reads next int, assigns to rank
while (read.hasNext()) //reads until end of text
{
String name2 = read.next(); //next string of next Object to be tested
int rank2 = read.nextInt(); //rank to test rank1 against
if (rank1 > rank2) //if current is higher priority than test
{
enQueue(name1, rank1); //enqueue the current object
name1 = name2; //move test name down to current
rank1 = rank2; //move test rank down to current
}
else
{
enQueue(name2, rank2); //enqueue the current object
}
}
read.close(); //ends read when empty
}
catch(Exception exec)
{
System.out.println("Error: file not found.");
}
}
I need to get this one single method to either pre-sort the objects without sending them to a list, or sorting them properly, one time, while on-the-fly, and I'm running out of ideas.
Conceptually (ignoring implementation) a priority queue is pretty simple. It needs to be able to add an item with a priority and it needs to be able to get the item with the highest (or, in some implementations, lowest) priority. An additional constraint that is sometimes included is that for two items with equal priority the item added first must be retrieved first.
So that's the concept. For us to help you might need to provide some more details on exactly how your priority queue is supposed to work. For the following notes I'll assume:
- retrieve highest priority first
- equal priority should be retrieved in insertion order
Looking at implementation, the underlying structure could be just about any collection as long as insertion is allowed and insertion order is preserved. The traditional implementation is a heap because they use memory efficiently and are very fast but a linked list (single or double) is fine functionally.
Clearly priority queues imply an order of retrieval. This can be implemented at insertion or retrieval time. Again this decision will be dictated by usage and again it seems your implementation can ignore these factors.
So my suggestion would be, to keep it simple, that you sort at insertion time rather than at retrieval time. Without supplying you actual code (which I'm assuming is your task) here's a basic algorithm that could implement an insertion time priority queue.
class PriorityItem {
private final Item item;
private final int priority;
}
Collection<PriorityItem> queue;
void insert(Item item, int priority) {
PriorityItem element = new PriorityItem(item, priority);
if queue is not empty {
step through queue {
if current.priority < priority {
insert element here
return
}
}
}
add element to end queue
}
Then retrieval is trivial: it's just the first item in the queue.
I want to create a method that loops though a circular linked list, Essentially mimicking a token ring network. I create a random number of either 0 or 1, if it is 0, it deletes the first item in the list. If it is one it just says they are still logged on.
So i should have something like this..
User A Logged on
User B logged off
User A logged off
When list is clear it terminates
The problem is it seems to always leave one particular user....How can I make this work?
public void log(){
if(start==null)
System.out.println("List is empty..");
else{
Node temp=start;
System.out.print("->");
//get rid of each user with a similar method but with a random user removed....
while(temp.next!=null && count>0)
{
int r = rand.nextInt(2);
if(r==0)
{
deleteAt(0);
System.out.println(" OFF"+temp.data);
}
else if(r==1)
{
System.out.println(" ON "+temp.data);
}
temp=temp.next;
}
//System.out.println(counter);
}
}
public void deleteFirst() {
Node temp=start;
while(temp.next!=start){
temp=temp.next;
}
temp.next=start.next;
start=start.next;
count--;
}
public void deleteAt(int position){
Node current=start;
Node previous=start;
for(int i=0;i<position;i++){
if(current.next==start)
break;
previous=current;
current=current.next;
}
if(position==0)
deleteFirst();
else
previous.next=current.next;
count--;
}
Deleting the last element from a circular linked list is a special case, because you need to set start to null. So you need to cater for that in your delete routines: test whether start->next == start.
Besides that, looping through the list while deleting elements requires special care: temp in the outer loop in log() can point to the removed element, rather than an element in the list. Taking temp=temp->next then may not be valid.
Also, count is decremented twice in deleteAt(0).