Create a java List with maximum of 100 values - java

I create a list of object with java
public class Cleint {
private int id;
private String user;
private int age;
public static List<Client> last100CleintList;
The list is supposed to be a kind of queue where the last 100 clients are stored. So when the list is empty I just want to add clients but when I reach 100 I want to delete the last one and add the new one. I could do it manually but is there a function for that? Or maybe in arrays, I am not forced to use lists.

There is no built-in library to achieve that (data-structure is there) without creating a utility method yourself.
Since you want to keep the last 100Clients every-time you append; and the list size is 100, you have to remove the first Client. You could try something like this (with Client objects).
import java.util.Queue;
import org.apache.commons.collections4.queue.CircularFifoQueue;`
Queue<String> circularQueue = new CircularFifoQueue<String>(2);
circularQueue.add("Bob");
circularQueue.add("Doe");
circularQueue.add("Joe");
then
System.out.println(circularQueue);
outputs ["Doe", "Joe"];
You can also do this with:
com.google.common.collect.EvictingQueue
MinMaxPriorityQueue by guava

Related

Allocate random priority in priority queue?

I am working on assigning random priorities (i.e. high, medium, low) to a list for a ServiceDesk assignment.
Before that, I was wondering how to go about storing (and printing) an array in said priority queue. This is currently what I have.
*UPDATED CODE
import java.util.*;
import java.util.Random;
public class Demo {
public static void main (String[] args) {
String [] names = {
"Tanya Turner","Juana Downs","Mac Bautista","Leanne Donaldson",
"Jere Romero","Autumn Hayden","Vincenzo Mckee","Penelope Stanley",
"Rose Solis","Randal Savage","Delia Hardy","Alisha Hebert","Johnson Jefferson",
"Gregorio Richard","Jana Simmons","Marian Shepherd","Lynn Pugh","Christine Newman",
"Essie Frederick","Jewel Oneill","Raul Coleman","Lou Glover","Cora Rush",
"Damien Norris","Omer Parsons","Adolph Petersen","Dane Proctor","Norbert Ritter",
"Gloria Dickerson","Ella Morton","Madeline Mccullough","Patsy Berger","Tory Hardin",
"Sonny Guzman","Kathrine Bond","Teodoro Bolton","Aimee Moran","Jerry Rhodes",
"Palmer Golden","Zelma Hobbs","Marcella Patel","Freddy Lucas","Ladonna Hutchinson",
"Devon Boone","Sue Graves","Chadwick Mcpherson","Antonia Rocha","Roseann Peters",
"Leif Riggs","Judith Mcbride","Frances Simon","Nora Cervantes","Alba Hickman",
"Concetta Wu","Chelsea Eaton","Dana Rocha","Hubert Kaiser","Phillip Stephenson",
"Estela Kent","Rene Hughes","Clement Gilmore","Arlie Fernandez","Teodoro Buckley",
"Daniel Chavez","Jeffry Shepherd","Devin Case","Eric Cooley","Dina Duncan","Teddy Price",
"Matthew Cooke","Andres Dalton","Clayton Fields","Vito Lara","Lynette Mccann","Greta Choi",
"Santo Noble","Thurman Douglas","Therese Norton","Juliette Graves","Fran Vang",
"Forrest Gibbs","Cameron Bernard","Tracy Zhang","Hugh Huerta","Jaime Huynh","Tami Cordova",
"Jami Mcpherson","Melissa Stein","Rayford Brewer","Tammie Lucero","Marcia Velez","Jasper Watkins",
"Cora Chapman","Vickie Mccarthy","Gino Pena","Chadwick Hutchinson","Antonio Bryan",
"Zachery Barnett","Randy Crawford","Laura Barton","Nolan Leach","Deborah Perry",
"Georgina Sanford","Heidi Anthony","Leah Hester","Dong Swanson","Genevieve Wagner",
"Russell Todd","Sherman Wolfe","Bo Schultz","Rosalyn Stevens","Brooke Moses","Jasmine Brock",
"Guadalupe Andersen","Emilio Horne","Clara Spencer","Raul Levine","Colton Adams","Eve Avila",
"Donny Murray","Laverne Valentine","Wilbert Gilbert","Justine Terrell","Waldo Nielsen",
"Erma Mason","Brandie Sullivan","Murray Torres","Angelique Whitney","Shanna Humphrey",
"Graig Farley","Lindsay Hines","Susanne Compton","Frankie Frank","Saundra Marks","Lorna Skinner",
"Josephine Boyle","Maynard Wagner","Ronda Potts","Elias French","Gilberto Nguyen"
};
String[] priority = {"High", "Medium", "Low"};
Random r = new Random();
for (String i : names) {
System.out.println("Names are: " + i);
int randomPriority = r.nextInt(priority.length);
System.out.println("Priority: " + priority[randomPriority]);
}
}
}
Sounds like you are asking for help on how to get started. You are asking for help on learning to learn. Here is how I would approach your problem:
Apparently you are supposed to use a priority queue.
Write a tiny program that makes a priority queue and stores strings into it, then prints them out.
Define a class and store instances of that class into the priority queue instead of strings.
Modify the sort criteria on the priority queue and notice that the printed sequence changes according to the sort criteria.
Write a function that creates one class instance with random values.
Write a function that creates all 100 class instances.
Declare victory.
A priority queue doesn't store priorities itself. Instead, it provides a hook where it asks "what's the priority of this item?" and your code responds with the priority. Consequently, it's on you to augment the items you're storing with their priorities.
In other words, you'll need to use a richer data format than just plain strings. You should probably store the names and their priorities side by side. It calls for a custom class with fields such as author and priority.
enum Priority {
LOW,
MEDIUM,
HIGH
}
class Ticket {
String author;
String description;
Priority priority;
}
You can assign random priorities when you create each Ticket.
The glue that'll bind the priority queue and the Ticket class is a custom comparator. Writing one is pretty straightforward using -> lambda syntax:
PriorityQueue<Ticket> queue = new PriorityQueue<>(
Comparator.comparing(ticket -> ticket.priority)
);

How to throttle request in a graph using akka stream?

Background
I have a project where we are using akka-streams with Java.
In this project I have a stream of strings and a graph that does some operations on them.
Objective
In my graph, I want to broadcast that stream to 2 workers. One will replace all characters 'a' with 'A' and send data as it receives it in real time.
The other one will receive the data, and every 3 strings, it will concat those 3 strings and map them to numbers.
It would look like the following:
Obviously Sink 2 will not receive information as fast as Sink 1. but that is expected behavior. The interesting part here, is worker 2.
Problem
Doing worker 1 is easy, and not hard. The issue here is doing worker 2. I know akka has buffers that can save up to X messages, but then it looks like I am forced to choose one of the existing Overflow strategies which often result in choosing which message I want to drop or if I want to keep the stream alive or not.
All I want is to, when my buffer in worke2 reaches the maximum size of the buffer, to perform the concat and map operations on all the messages it has, and then send them along ( resetting the buffer after ).
But even after reading the stream-rate documentation for akka I couldn't find a way of doing it, at least using Java.
Research
I also checked a similar SO question, Selective request-throttling using akka-http stream however it has been over an year and no one has responded.
Questions
Using the graph DSL, how would I create the path from:
Source -> bcast -> worker2 -> Sink 2
??
After your bcast apply the groupedWithin operator with an unlimited duration and a number of element set to 3.
https://doc.akka.io/docs/akka/2.5/stream/operators/Source-or-Flow/groupedWithin.html
You can also do it yourself, adding a stage that stores element in a List and emit the list every time it reaches 3 elements.
import akka.stream.Attributes;
import akka.stream.FlowShape;
import akka.stream.Inlet;
import akka.stream.Outlet;
import akka.stream.stage.AbstractInHandler;
import akka.stream.stage.GraphStage;
import akka.stream.stage.GraphStageLogic;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
public class RecordGrouper<T> extends GraphStage<FlowShape<T, List<T>>> {
private final Inlet<T> inlet = Inlet.create("in");
private final Outlet<List<T>> outlet = Outlet.create("out");
private final FlowShape<T, List<T>> shape = new FlowShape<>(inlet, outlet);
#Override
public GraphStageLogic createLogic(Attributes inheritedAttributes) {
return new GraphStageLogic(shape) {
List<T> batch = new ArrayList<>(3);
{
setHandler(
inlet,
new AbstractInHandler() {
#Override
public void onPush() {
T record = grab(inlet);
batch.add(record);
if (batch.size() == 3) {
emit(outlet, ImmutableList.copyOf(batch));
batch.clear();
}
pull(inlet);
}
});
}
#Override
public void preStart() {
pull(inlet);
}
};
}
#Override
public FlowShape<T, List<T>> shape() {
return shape;
}
}
As a side node, I don't think the buffer operator will work as it only kicks in when there's backpressure. So if everything is quiet, elements will still be emitted one by one instead of 3 by 3. https://doc.akka.io/docs/akka/2.5/stream/operators/Source-or-Flow/buffer.html

how to reorder a list of objects?

Firstly, this is going to sound like homework, but it ain't. Just a problem I'm trying to solve at work.
I have a list of objects, the objects have a sequence number which indicates their order in the list in the UI. Example:
public class Task {
Long id;
String name;
Long seq;
}
The table in my UI has "up" and "down" links on each row of the table for moving the tasks up and down in the list.
I'm implementing two methods to handle the reordering. These methods are call by ajax in the web UI.
public void incTaskSeq(List<Task> allTasks, Task taskToMove)
For example; if I have t1.seq=1, t2.seq=2, t3.seq=3, t4.seq=4, t5.seq=5 and I want to increment the place of t3, then t3.seq becomes 4, and t4.seq must become 3.
public void decTaskSeq(List<Task> allTasks, Task taskToMove)
Similarly; if I have t1.seq=1, t2.seq=2, t4.seq=3, t3.seq=4, t5.seq=5 and I want to decrement the place of t4, then t4.seq becomes 2, and t2.seq must become 3. Resulting in:
t1.seq=1, t4.seq=2, t2.seq=3, t3.seq=4, t5.seq=5
I'm a little stuck on the best way to do this.
I was thinking of putting all the tasks in a HashMap and then sort the map by the sequence number. Then locate the taskToMove in the map, change the sequence number, and then change all the affected tasks sequences.
But this approach seems inelegant. Does anyone have any ideas how I should do this?
Thanks, Rob
Use a Comparator, which is the Java interface for sorting non-naturally.
public TaskSequenceComparator implements Comparator<Task> {
public int compare(Task one, Task two) {
return one.getSequence() - two.getSequence();
}
}
...
List<Task> tasks = ...;
Collections.sort(tasks, new TaskSquenceComaprator());
// tasks is now sorted by sequence.
You can create multiple Comparator classes to implement each kind of supported sort. Then you can select from them when you need the list sorted in a particular manner.
Implement a Comparator for each criteria you want to sort for.
Create a new ordered Collection object (maybe a TreeSet) passing it the Comparator needed. Do .addAll of the objects.
Just let the List keep tarck of ordering. (Except You always need to update the seqence number).
public void incTaskSeq(List<Task> allTasks, Task taskToMove){
int movTaskNum = 0;
for(int i=0;i<allTasks.size();i++){
if(allTasks.get(i).equals(taskToMove))
movTaskNum = i;
}
allTasks.remove(taskToMove);
allTasks.add(i-1, taskToMove);
}
sorry for typos
Use a doubly linked list and swap the sequence numbers when you move an item.

Problems merging multiple objects into a complex object for Morphia

I'm trying to merge these three objects into a single complex object:
public class Person {
private String name;
private List<Event> events;
// getters and setters
}
public class Event {
private String name;
private List<Gift> gifts;
// getters and setters
}
public class Gift {
private String name;
private String recipient;// the name of the person
private String eventName;
// getters and setters
}
My goal is to save the Person object in MongoDB using Morphia and this how I want my document laid out. I've created a document builder, of sorts, that combines lists of each object. Each Person gets a list of all Events, but can only receive specific Gifts. While my document builder does create a document that Morphia can persist, only the Gifts of that last recipient (sort order) are inserted into the Events for all Persons. Though for the correct Events.
public void merge() {
for (Person person : listOfPersons) {
for (Event event : listOfEvents) {
// somePersonsGifts: a sublist of gifts based on Event and Person.
List<Gift> somePersonsGifts = new ArrayList<Gift>();
for (Gift gift : listOfGifts) {
if (person.getName().equals(gift.getRecipient()) && gift.getEventName().equals(event.getName())) {
somePersonsGifts.add(gift);
}
}
event.setGifts(somePersonsGifts);
}
person.setEvents(listOfEvents)
}
}
If I modify the code slightly to process one person at a time by removing the outer loop and having the method take an argument for specific index of the Persons list:
public void merge(int p) {
Person person = listOfPersons.get(p);
//...and so on
I get one complete Person object with the correct gifts. If try to feed the this modified version into a loop, the problem comes back. I've tried using regular for-loops and synchronized collections. I've tried using Google Guava's ImmutableArrayList and still no luck. I know the problem is that I'm changing the lists while accessing them but I can't find anyway around it. I wrote a DAO that uses the MongoDB driver directly and it works properly, but it's a lot more code and quite ugly. I really want this approach to work, the answer is in front of me but I just can't see it. Any help would be greatly appreciated.
Here is your problem:
List<Gift> somePersonsGifts = new ArrayList<Gift>();
....
event.setGifts(somePersonsGifts);
You add the gifts only for one person; if you want to aggregate all the gifts into the event, re-use the existing list.
I don't know anything about MongoDB or Morphia but I suspect the problem is your use of the setters event.setGifts(somePersonsGifts) and person.setEvents(events). Your code does not seem to merge the existing gift and event lists with the ones you are calculating further in the loop, which is how you would want it to behave (if I understand the question correctly).
You should retrieve the allready existing gift list (and event list too) instead of overwriting them with empty new ones.
I don't know if the method merge() is inside the list but I assume that since you are using the list events here
person.setEvents(events);
Maybe you meant
person.setEvents(listOfEvents)
Notice that you are adding all the events to each person. If all the persons went to all the events, it is unnecessary to have the events inside the person.

Java: linked list of items problem

I have used linked lists before with Strings, doubles, etc., and they always worked exactly as expected. But now I am forming a linked list of items, and whenever I add a new element to the list, all objects in the list apparently become equal to the last object.
The essential code is as below:
import java.util.*;
public class Global
{
static public LinkedList<StockInfo> DiaryStocks = new LinkedList<StockInfo>();
static public class StockInfo //info related to each stock in diary
{
String recordDate;
String ticker;
int status;
String buyDate;
String sellDate;
double buyPrice;
double sellPrice;
double nmbrShares;
}//StockInfo
//The following function places the Diary data for a stock in the arraylist
static public void AddDiaryData(StockInfo thisdata)
{
String tckr;
int i;
DiaryStocks.add(thisdata);
for (i = 0; i < DiaryStocks.size(); i++) //this is debug code
{
tckr = DiaryStocks.get(i).ticker;
}
}
}
As I said, when single stepping through the debug code near the bottom, each time I add a new item to the list, the list size grows as it should, but the tckr item only corresponds to the last item added.
Any insights into this puzzle would be greatly appreciated.
John Doner
The problem is outside the code your provide. It is most likely that you are adding the same instance of StockInfo. Perhaps you have something like:
StockInfo info = new StockInfo();
for (...) {
info.setFoo(..);
info.setBar(..);
AddDiaryData(info);
}
You should not reuse instances like that. You should create a new instance each time.
As a sidenote - method names in Java should start with lowercase letter.
From the symptoms you are describing, it seems as if you are always adding a reference to the same StockInfo object instance to your list, rather than a reference to a new copy each time.
When that object is updated with the contents of the new entry, all list entries appear to change to reflect that latest entry.
This problem lies outside the code snippet that you posted, perhaps in the caller of the AddDiaryData method.
Ooops.
Deep Copy please search it
DiaryStocks.add(thisdata);
you should create new StockInfo() then add to the list otherwise you add the reference and it equalize all the reference of items to the last one

Categories