Merge Queues in Java - java

I was wondering whats the best way to write a method to merge an ArrayQueue with another Queue without removing any elements from the q thats passed.
eg. queue1 = [1,2,3,4] and queue2 = [5,6,7,8,9,10].
When queue1.mergeQs(queue2) was called it would create queue1 = [1,5,2,6,3,7,4,8,9,10] whilst queue2 would remain [5,6,7,8,9,10]
public void mergeQs(ArrayQmerge q){}
This way seems harder to implement than if you were to pass both Queues and return a new merged Queue. Thanks.
Just to clarify, i'm looking for a method to interleave the elements from the two queues.

One detail that might help you is that private fields are visible between different object of the same class in Java. That means that as long as you only intend to merge queues of your own class, your code has full access to all internal fields, such as the array you use to store your elements.
For the simplest case, where all elements are stored in a linear array with the queue head being at index zero, something like this might be a start:
public void mergeQs(ArrayQmerge q) {
Object[] array = new Object[this.size() + q.size()];
int i;
int o;
// Interleave elements
for (i = 0, o = 0; i < this.size() && i < q.size(); ++i) {
array[o++] = this.array[i];
array[o++] = q.array[i];
}
// Copy the remaining elements
while (i < this.size()) {
array[o++] = this.array[i++];
}
while (i < q.size()) {
array[o++] = q.array[i++];
}
this.array = array;
}

You can create a new Queue locally in the merge method, then assign your class's queue to the local version.

Since you are using your own homebrew ArrayQueue then this is conjecture.
Creating a new queue and returning is as I think you already say is way easier, and more efficient, as inserting elements into an Array backed structure will involve shuffling the rest of the elements down one position for each insert op.
An alternative is to implement public void mergeQs(ArrayQmerge q) by swapping out the underlying array you have backing it. So you get the same easy implementation as returning a new Queue but with the same in place side effect.

Related

Get max element in a Queue | Java

Is there an alternative way to get the max element in a Queue (Java)?
(Please provide alternative approaches )
import java.util.*;
public class MaxQueueElement<E extends Comparable<E>> {
public MaxQueueElement(Queue<E> queue){
E max= queue.peek(); // initialize max with head of queue
for(E e : queue){
if(e.compareTo(max) > 0){
max = e;
}
}
System.out.println(max);
}
}
The get-max operation on a queue can be implemented in amortized O(1) time by maintaining the candidates for the max value in a separate double-ended queue (Deque).
On enqueue (or offer) operation, we check whether there are any elements at the back of the Deque which are lesser in value than the element being enqueued. These values can simply be removed – for these can never be the maximum value going forward.
On dequeue (or poll) operation, we check whether the first element in the Deque is equal to the first element in the regular queue and if yes, remove it too.
The max element is simply the first element of the Deque.
All operations have amortized O(1) time complexity.
Here's an implementation in Java:
public class QueueWithMax<T extends Comparable<T>> {
Queue<T> queue;
Deque<T> cMax; // candidates for Max value
public QueueWithMax() {
queue = new LinkedList<>();
cMax = new LinkedList<>();
}
public void offer(T element) {
queue.offer(element);
while (!cMax.isEmpty() && element.compareTo(cMax.peekLast()) > 0) {
cMax.pollLast();
}
cMax.offerLast(element);
}
public T poll() {
if (cMax.peekFirst().equals(queue.peek()))
cMax.pollFirst();
return queue.poll();
}
public T getMax() {
return cMax.peekFirst();
}
}
The only way to access all elements in a Queue is to use the iterator() method - you can't (generally) access the elements by index (as in, some implementations might, but Queue doesn't inherently).
As such, all you can do is to iterate the elements one at a time, storing the current maximum element. This is exactly what you're doing here.
There is nothing wrong with your algorithm - but the way you've implemented it could be improved:
Don't do this in the constructor of a class - you don't need to construct a new instance of anything, as the maximum value already exists. Do it in a (static) method.
Don't print out the result - that's of no use to man or beast. Return it to the caller.
Handle the cases where the queue is empty and may contain nulls. (Look at the Javadoc of Collections.max for ideas)
I'm taking a computer science class, and we aren't allowed to use the for each loop. I'm not sure if it's the same with you. Note that the for each loop kind of defeats the purpose of a Queue since you want to only be handling the front and end of a queue. In my class specifically, we also want to have the queue be at it's original state before it was passed into the method without using an extra auxiliary data structure. Here's how I would go about it on a test:
public E findMaxQueueElement(Queue<e> queue) { //my test would ask me to return the max value
E max = queue.remove();
queue.add(max); //add it back to the end
for(int i=0; i<queue.size()-1; i++) {
E current = queue.remove();
if (current.compareTo(max) > 0) {
max = current;
}
queue.add(current);
}
return max;
}
With the limitations I provided, this should work. I hope this helps.
You can use Java 8's stream to sort the Queue, it internally uses the same algorithm but will result in less noisy code, e.g.:
public void MaxQueueElement(Queue<E> queue){
Optional<E> max = queue.stream()
.max(Comparable::compareTo);
if(max.isPresent()){
System.out.println(max.get());
}
}
Another approach would be to use PriorityQueue with comparator and get the first element from it. e.g.:
public void MaxQueueElement2(Queue<E> queue){
PriorityQueue<E> pQueue = new PriorityQueue<>((E e1, E e2)->e1.compareTo(e2));
pQueue.addAll(queue);
System.out.println(pQueue.peek());
}
Unless the queue is not some special sorted queue like PriorityQueue, from the algorithmic point of view there is no better way. Since the queue does not have any intrinsic sorting properties, you have to check all the elements of the queue before you find one.
The code is more or less OK. It will fail if the queue contains null. This is normally not the case, but may happen.
The MaxQueueElement construct is somewhat strange.
I think you can also make use of
Collections.max(queue) in case of queue

Move Elements In An ArrayList Down One That Are Higher Than Specific Index

I have a server that creates a new Thread when a client joins and puts it in an ArrayList (that is of the type EchoThread). It works great - creates a new JLabel for each one and updates their positions in my game near instantly, however if one leaves (that isn't the last client in the arraylist) then I want the server to move all of the clients (that are higher than the index of the client that left) down by one. I have tried many things, some partially working. Here is the method if somebody leaves, where i is equal to the index of the client that left:
public static void removeClient(int i) throws Exception {
}
I tried a couple of things, such as using a for loop to move each of the EchoThread's in the arrayList down by one, however they dont seem to work:
The ArrayList:
static ArrayList<EchoThread> clients = new ArrayList<EchoThread>();
The for loop that I tried:
for(int ii = i+1; ii < clients.size()-1; ii++){
EchoThread e = clients.get(ii);
clients.set(ii-1, e);
}
I also tried to make a temporary arraylist that gets all of the elements in the clients arraylist added, except the index i, and then set the clients arraylist to equal the temporary arraylist, but it still failed.
Somebody said I could use a linked list, but I don't know how?
Edit:
p = a JPanel
f = a JFrame
clients = an arrayList<EchoThread>
clientinfo = a JLabel in EchoThread class
clientname = an arraylist of strings
clientpos = an arraylist of the positions of each client
info = a JLabel to show number of clients that are connected
Method:
public static void removeClient(int i) throws Exception {
p.remove(clients.get(i).clientinfo);
p.revalidate();
f.validate();
f.repaint();
clients.get(i).clientinfo.setVisible(false);
clients.remove(i);
clientnames.remove(i);
clientpos.remove(i);
info.setText("Clients Connected: " + clients.size());
for(int ii = i+1; ii < clients.size()-1; ii++){
EchoThread e = clients.get(ii);
clients.set(ii-1, e);
}
}
You must make sure you are calling removeClient in a thread-safe way. I'm guessing but it sounds like perhaps you're calling it from each EchoThread, which is not safe without synchronization, because (a) the threads can trample all over each other's modifications to the list; and (b) there is no guarantee threads will even see each other's modifications to the list.
Usually you could just add the synchronized modifier on any methods that modify the ArrayList, which provides both mutual exclusion (preventing multiple threads from modifying it at once and corrupting it) and a happens-before relationship between calls to those methods (making sure threads see each other's changes to the list). However, that won't be enough here, because you are also using the method to modify Swing components. With few exceptions, Swing components must be accessed only from the single event dispatch thread, so if you want to update the frame and you are on a different thread, you must first switch to the event dispatch thread.
In Java 8+, modify the beginning of your removeClient method as follows:
public static void removeClient(int i) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(() -> removeClient(i));
return;
}
// ...
In old versions of Java:
public static void removeClient(final int i) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
removeClient(i);
}
});
return;
}
// ...
Once you are on the correct thread, removing the item from the list and moving the other items down the list really is as simple as calling clients.remove(i);, as the other answerers have said. You don't need that extra for-loop and it won't work.
Perhaps your problem is that although the list does move the items down, you have given those items their own index field, so after removing the item, its own index field no longer matches its actual position in the list? You could iterate the items in the list and reset the index field of each item to match its real position:
for (int i = 0; i < clients.size(); i++)
clients.get(i).index = i;
(assuming you have some field index on your EchoThread objects).
However, that might not be the best approach. You don't necessarily need to keep track of the index, since you can perfectly well remove the object itself without knowing the index:
EchoThread client = ...;
clients.remove(client);
How to update your other lists, clientnames, clientpos? Well, you could find out the index by calling indexOf on the first list. But that is ugly. You shouldn't really have all these separate lists. You should preferably have a class that encapsulates the various different fields for a single client including the "name" and "pos" fields, and make a list of those objects. You already have the EchoClient objects, so maybe you can just move the fields to that.
The API already does this for you with the remove method.
Taken from the docs:
public E remove(int index)
Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).
have you tried clients.remove(i);
Here's the implementation of ArrayList#remove. As you can see, it uses System.arraycopy to slide the tail of the list down so you have an uninterrupted list.
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*
* #param index the index of the element to be removed
* #return the element that was removed from the list
* #throws IndexOutOfBoundsException {#inheritDoc}
*/
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}

ArrayIndexOutOfBoundsException while converting linkedList to array list

Im trying to convert a linkedList into an ArrayList as shown below.
private LinkedList<myData> myLinkedList= new LinkedList<myData>();
public Collection<myData> getData()
{
return new ArrayList<myData>(myLinkedList);
}
The linkedList might be updated by multiple threads. While testing in production I get the below error. The error is not consistant. So i get it may be once in a week, month or so.
java.lang.ArrayIndexOutOfBoundsException: 15
at java.util.LinkedList.toArray(LinkedList.java:866)
at java.util.ArrayList.<init>(ArrayList.java:131)
at org.xxx.yyy.zzz.getData(Data.java:291)
Is there any way it could be related to concurrent modification of the linkedList. Appreciate any help on this.
toArray failing is only one symptom of you doing something fundamentally dangerous.
From the documentation of LinkedList:
If multiple threads access a linked list concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
You'll either need to add synchronization (not just for toArray, but basically all uses of the list) or use one of the concurrent collections which is designed to be thread-safe.
LinkedList#toArray() is implemented as such (Oracle JDK 7)
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node<E> x = first; x != null; x = x.next)
result[i++] = x.item;
return result;
}
If you add to the LinkedList after the result array is constructed but before the for loop, then the array access expression inside the for loop will cause an ArrayIndexOutOfBoundsException when trying to access an index larger than the original size.
You should really put some synchronization barriers so that doesn't happen.

Get the array from an AtomicLongArray

Using Java 1.6 and the AtomicLongArray, I'd like to "copy" the original AtomicLongArray into a new one. There is a constructor that takes an array (AtomicLongArray(long[])), so I thought I could just get the array from the original one and give it to the constructor.
Sadly, the actual long[] in the AtomicLongArray is private and there seem to be no getters for it. Is there any way to do this, meaning copy the values from one AtomicLongArray to another? I can't create my own class based on this class, as the sun.misc.Unsafe class is not available to me.
This is needed because I'm going to iterate over the values, and I don't want them modified by another thread during iteration. So I thought I could make a copy and use that for the iteration...
Thanks!
Phillip
I suspect you have to create your own long[] and populate it first, or just iterate over the original:
AtomicLongArray copy = new AtomicLongArray(original.length());
for (int i = 0; i < copy.length(); i++)
{
copy.set(i, original.get(i));
}
Note that although each individual operation in AtomicLongArray is atomic, there are no bulk operations - so there's no way of getting a "snapshot" of the whole array at time T. If you want that sort of behaviour, I believe you'll need to use synchronization.
This data structure allows concurrent updates to individual entries in the collection. There is not overall lock, so you can't prevent another thread changing the contents while you are iterating over it.
If you need this, you need a workaround, e.g. copy the array and loop again to check it hasn't changed. If changed, repeat. Or you need a collection which supports a global lock.
long[] copy = new long[original.length()];
boolean changed = true;
// repeat until we get an unchanged copy.
while(true) {
for (int i = 0; i < copy.length(); i++) {
long l = original.get(i);
changed |= copy[i] != l;
copy[i] = l;
}
if (!changed) break;
changed = false;
}
This is not completely safe, but may be enough for what you need.

Better practice to re-instantiate a List or invoke clear()

Using Java (1.6) is it better to call the clear() method on a List or just re-instantiate the reference?
I have an ArrayList that is filled with an unknown number of Objects and periodically "flushed" - where the Objects are processed and the List is cleared. Once flushed the List is filled up again. The flush happens at a random time. The number within the List can potentially be small (10s of Objects) or large (millions of objects).
So is it better to have the "flush" call clear() or new ArrayList() ?
Is it even worth worrying about this sort of issues or should I let the VM worry about it? How could I go about looking at the memory footprint of Java to work this sort of thing out for myself?
Any help greatly appreciated.
The main thing to be concerned about is what other code might have a reference to the list. If the existing list is visible elsewhere, do you want that code to see a cleared list, or keep the existing one?
If nothing else can see the list, I'd probably just clear it - but not for performance reasons; just because the way you've described the operation sounds more like clearing than "create a new list".
The ArrayList<T> docs don't specify what happens to the underlying data structures, but looking at the 1.7 implementation in Eclipse, it looks like you should probably call trimToSize() after clear() - otherwise you could still have a list backed by a large array of null references. (Maybe that isn't an issue for you, of course... maybe that's more efficient than having to copy the array as the size builds up again. You'll know more about this than we do.)
(Of course creating a new list doesn't require the old list to set all the array elements to null... but I doubt that that will be significant in most cases.)
The way you are using it looks very much like how a Queue is used. When you work of the items on the queue they are removed when you treat them.
Using one of the Queue classes might make the code more elegant.
There are also variants which handle concurrent updates in a predictable way.
I think if the Arraylist is to be too frequently flushed,like if it's run continuously in loop or something then better use clear if the flushing is not too frequent then you may create a new instance.Also since you say that elements may vary from 10 object to millions you can probably go for an in-between size for each new Arraylist your creating so that the arraylist can avoid resizing a lot of time.
There is no advantage for list.clear() than new XXList.
Here is my investigation to compare performance.
import java.util.ArrayList;
import java.util.List;
public class ClearList {
public static void testClear(int m, int n) {
List<Integer> list = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
list.add(Integer.parseInt("" + j + i));
}
list.clear();
}
System.out.println(System.currentTimeMillis() - start);
}
public static void testNewInit(int m, int n) {
List<Integer> list = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
list.add(Integer.parseInt("" + j + i));
}
list = new ArrayList<>();
}
System.out.println(System.currentTimeMillis() - start);
}
public static void main(String[] args) {
System.out.println("clear ArrayList:");
testClear(991000, 100);
System.out.println("new ArrayList:");
testNewInit(991000, 100);
}
}
/*--*
* Out:
*
* clear ArrayList:
* 8391
* new ArrayList:
* 6871
*/

Categories