Record with operations on a list Java - java

I have a class MyList,in Java, with some basics operations like add,get and remove.Also in my list I must have a record with operations which have done with the list.How I can do this record?

You have to define a new class atribute. It can be a String. Like this:
public MyList{
private String record;
....
}
Then on each of your methods you update this atribute:
record += "\n"+*the operation*;
But if you want a better performance, you should use a StringBuffer instead of a String (see here).
Was this the answer that you wanted?

if I understand you want to keep track of updates made to MyList in order to have an history of what has been done.
Why not creating a ListHistory class
public class ListHistory {
private Action action;
private Object data;
public ListHistory(Action action, Object data) {
this.action = action;
this.data = data;
}
}
and the Action enum type (so you can make it evolve)
public enum Action {
get, add, remove;
}
and define a private List<ListHistory> history; variable to keep track of updates ?
You then have the ability to manipulate the history list as you want, add date to ListHistory if needed (or use a Map<Date, ListHistory>)
Hope this will help.
regards,
Yann

Related

How to make code dynamic for similar kind of blocks

I am creating my web page with vaadin where I need to create same kind of blocks for different type for example need to show blocks having car details, so only car name would be different but the block design would be same with same label but different labels. I want to write generic code so that i can expand it for any car name, without adding it manually.
Attaching the code snippet which i am using where i am repeating my code for different type. Want to implement it dynamically.
private Grid<PresentableGenerateInputHeaders> winTSHeaderColumnsGrid;
private Grid<PresentableGenerateInputHeaders> fRHeaderColumnsGrid;
private ListDataProvider<PresentableGenerateInputHeaders> listDataProvider;
private List<PresentableGenerateInputHeaders> presentableGenerateInputHeaders = new ArrayList<>();
private void initWinTsGrid() {
listDataProvider = new ListDataProvider<>(presentableGenerateInputHeaders);
winTSHeaderColumnsGrid = new Grid<PresentableGenerateInputHeaders>(PresentableGenerateInputHeaders.class);
winTSHeaderColumnsGrid.setDataProvider(listDataProvider);
winTSHeaderColumnsGrid.setCaption(i18n.get("view.ruleDetails.general.csvHeaderColumns"));
winTSHeaderColumnsGrid.setStyleName("a-units");
winTSHeaderColumnsGrid.setWidth("450px");
winTSHeaderColumnsGrid.setItems(addGridValues(DataSource.WIN_TS, winTSHeaderColumnsGrid));
winTSHeaderColumnsGrid.getEditor().setEnabled(true);
winTSHeaderColumnsGrid.setColumnOrder("header", "count");
winTSHeaderColumnsGrid.sort("header");
winTSHeaderColumnsGrid.getEditor().addSaveListener((EditorSaveEvent<PresentableGenerateInputHeaders> event) -> {
event.getGrid().select(event.getBean());
selectedGapFillingCountWINTS.add(event.getBean());
});
}
private void initFRGrid() {
listDataProvider = new ListDataProvider<>(presentableGenerateInputHeaders);
fRHeaderColumnsGrid = new Grid<PresentableGenerateInputHeaders>(PresentableGenerateInputHeaders.class);
fRHeaderColumnsGrid.setDataProvider(listDataProvider);
fRHeaderColumnsGrid.setCaption(i18n.get("view.ruleDetails.general.csvHeaderColumns"));
fRHeaderColumnsGrid.setStyleName("a-units");
fRHeaderColumnsGrid.setWidth("450px");
fRHeaderColumnsGrid.setItems(addGridValues(DataSource.FR, fRHeaderColumnsGrid));
fRHeaderColumnsGrid.getEditor().setEnabled(true);
fRHeaderColumnsGrid.setColumnOrder("header", "count");
fRHeaderColumnsGrid.sort("header");
fRHeaderColumnsGrid.getEditor().addSaveListener((EditorSaveEvent<PresentableGenerateInputHeaders> event) -> {
event.getGrid().select(event.getBean());
selectedGapFillingCountFR.add(event.getBean());
});
}
You can change methods to be more generic by identifying all the parts you don't want to keep static, and moving those to be populated by method parameters instead. I.e. instead of
private void myMethod() {
grid.setCaption("myCaption");
}
you would write
private void myMethod(String caption) {
grid.setCaption(caption);
}
and then call it
myMethod("myCaption");
If you need to be outside of the whole class to be able to determine what the real values are, you can for example make the method public or pass on the necessary values in the class constructor.
public MyClass(String gridCaption) {
myMethod(gridCaption);
}
If there are a lot of values you need to set dynamically, you might consider using an object that contains all the necessary values instead.
public void myMethod(MyPojo pojo) {
grid.setCaption(pojo.getGridCaption());
}
In your example it looks like the generic values you want to pass are DataSource dataSource and whatever type of collection selectedGapFillingCountWINTS and selectedGapFillingCountFR happen to be, and the method should probably return the grid rather than set it directly to a class variable.

how to make ArrayList accessible by all JFrames and how to update it?

So I'm making a mock Starbucks app and I want that everytime a customer clicks the "Order" button, the product is added to an ArrayList and for this ArrayList to be accessed by all. I'm kind of confused where to insert the global ArrayList code...
This is code for my btnOrder:
private void btnOrderActionPerformed(java.awt.event.ActionEvent evt) {
String name = lblName.getText();
String size = cmbSize.getSelectedItem().toString();
int quantity = (int) spnrQuantity.getValue();
int price=0;
if (size.equals("Tall 12oz")) {
price = 170;
} else if (size.equals("Grande 16oz")) {
price = 180;
} else if (size.equals("Venti 20oz")) {
price = 190;
}
Global.list.add(new Object());
new Receipt(name, size, quantity, price).setVisible(true);
}
This is code for my Receipt frame which contains the JTable so I can display orders:
public class Receipt extends javax.swing.JFrame {
/**
* Creates new form Receipt
*/
public Receipt() {
initComponents();
}
String size, name;
int quantity, price;
public Receipt(String name, String size, int quantity, int price) {
initComponents();
this.name = name;
this.size = size;
this.quantity = quantity;
this.price = price;
addToTable();
}
void addToTable() {
DefaultTableModel table = (DefaultTableModel) tblCart.getModel();
Vector v = new Vector();
v.add(name);
v.add(size);
v.add(price);
v.add(quantity);
table.addRow(v);
}
And this is the code for the accessible ArrayList:
public class Global {
public static ArrayList<Object> list = new ArrayList<>();
private Global(){
}
}
Managing global state can be a nightmare, while you can use a singleton to solve the issue, it violates the Single responsibility principle. It also removes access control, allowing anyone to modify the list in whatever way they see fit without control.
Another solution is to use some kind of model, which can passed between the various components, if you make clever use of interfaces, you can control who can do what and when.
This is a core concept of Model-View-Controller and program to interface not implementation principle.
The basic idea is you would create a "model" which maintains the data you want to share, in this, primarily the items in the customer's order (and maybe the customer's name)
You would create an appropriate order and pass a reference of it to the "order" view, where it would be able to add/remove/update items to the model. When complete, the "controller" would then pass the same instance of the model to the "check-out" view, which would use this information to generate a bill (and possibly a payment information) and finally store the transaction
You would then be able to take the information from the model at the end and tell what has happened.
Because there are complex states you might need to control, you might need more than one model, for example, you could pass the "order" model to the "check-out" view, but it could create a "transaction" model, which wraps the "order" model
You can take use Singleton design pattern here. With Singletons, you can take advantage of Polymorphism which won't be possible with static objects.
enum Global {
INSTANCE;
private ArrayList<Object> list = new ArrayList<>();
public void add(Object obj) {
//custom validations (if any)
list.add(obj);
}
public Object get(int index) {
//check here for permissions, validations etc...
return list.get(index);
}
//other methods to access your shared objects
...
}
In this example, singleton pattern is implemented using ENUMs which ensures thread safety. You can also implement singleton using The ‘Inner Class’ Approach which is also thread safe.
Usage
private void btnOrderActionPerformed(java.awt.event.ActionEvent evt) {
...
Global.INSTANCE.add(new Object());
new Receipt(name, size, quantity, price).setVisible(true);
}
Difference between static class and singleton pattern?

How to populate map of string and another map in a thread safe way?

I am working on measuing my application metrics using below class in which I increment and decrement metrics.
public class AppMetrics {
private final AtomicLongMap<String> metricCounter = AtomicLongMap.create();
private static class Holder {
private static final AppMetrics INSTANCE = new AppMetrics();
}
public static AppMetrics getInstance() {
return Holder.INSTANCE;
}
private AppMetrics() {}
public void increment(String name) {
metricCounter.getAndIncrement(name);
}
public AtomicLongMap<String> getMetricCounter() {
return metricCounter;
}
}
I am calling increment method of AppMetrics class from multithreaded code to increment the metrics by passing the metric name.
Problem Statement:
Now I want to have metricCounter for each clientId which is a String. That means we can also get same clientId multiple times and sometimes it will be a new clientId, so somehow then I need to extract the metricCounter map for that clientId and increment metrics on that particular map (which is what I am not sure how to do that).
What is the right way to do that keeping in mind it has to be thread safe and have to perform atomic operations. I was thinking to make a map like that instead:
private final Map<String, AtomicLongMap<String>> clientIdMetricCounterHolder = Maps.newConcurrentMap();
Is this the right way? If yes then how can I populate this map by passing clientId as it's key and it's value will be the counter map for each metric.
I am on Java 7.
If you use a map then you'll need to synchronize on the creation of new AtomicLongMap instances. I would recommend using a LoadingCache instead. You might not end up using any of the actual "caching" features but the "loading" feature is extremely helpful as it will synchronizing creation of AtomicLongMap instances for you. e.g.:
LoadingCache<String, AtomicLongMap<String>> clientIdMetricCounterCache =
CacheBuilder.newBuilder().build(new CacheLoader<String, AtomicLongMap<String>>() {
#Override
public AtomicLongMap<String> load(String key) throws Exception {
return AtomicLongMap.create();
}
});
Now you can safely start update metric counts for any client without worrying about whether the client is new or not. e.g.
clientIdMetricCounterCache.get(clientId).incrementAndGet(metricName);
A Map<String, Map<String, T>> is just a Map<Pair<String, String>, T> in disguise. Create a MultiKey class:
class MultiKey {
public String clientId;
public String name;
// be sure to add hashCode and equals
}
Then just use an AtomicLongMap<MultiKey>.
Edited:
Provided the set of metrics is well defined, it wouldn't be too hard to use this data structure to view metrics for one client:
Set<String> possibleMetrics = // all the possible values for "name"
Map<String, Long> getMetricsForClient(String client) {
return Maps.asMap(possibleMetrics, m -> metrics.get(new MultiKey(client, m));
}
The returned map will be a live unmodifiable view. It might be a bit more verbose if you're using an older Java version, but it's still possible.

Why make a collection unmodifiable?

I know how to make a collection unmodifiable in java but I dont understand the need for such a method to exist. Can someone please explain this with an example scenario where I would want to make my collection unmodifiable?
Thanks in advance
The most efficient way to share private data outside of a class is to simply return it. But then something outside of the class can change the data that the class depends on. Another option is to copy the data before you share. This takes time and memory to do. Unmodifiable collections will often wrap the data and simply present it without allowing an outside class to edit it. This is faster than making a copy. An outside class can optionally make a modifiable copy if it needs.
An unmodifiable collection is basically read-only which is exactly what you want in case you need to publish such collection to client code and you don't want the client code to modify the collection.
It also promotes immutability which is generally a good thing since you won't have to care about the state of the collection for the rest of the execution of your program. See item 15 of Effective Java (2nd Edition) : Minimize mutability, and to quote Joshua Bloch :
Immutable objects are simple. An immutable object can be in exactly
one state, the state in which it was created.
Note that an unmodifiable collection will not make the contained objects immutable. This is a property each of the contained objects needs to make sure of, if it is required of course.
Take a look at this scenario. There is an application that creates 2 users, and then wants to notify them about something. But only users with name different from Peter should get the notification.
So we have to User.class:
public class User {
private String name;
private Integer id;
public User(final Integer id, final String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public Integer getId() {
return id;
}
}
The users are stored in special holder class (containing map):
public class UsersHolder {
private static Map<Integer, User> usersMap = new HashMap<Integer, User>();
public static void addUser(final User user) {
usersMap.put(user.getId(), user);
}
public static Map<Integer, User> getUsersMap() {
return usersMap;
//return Collections.unmodifiableMap(usersMap);
}
}
Then we have the UsersCreator that creates those users and stores them in a map:
public class UsersCreator {
public static void createUsers() {
UsersHolder.addUser(new User(1, "Peter"));
System.out.println("Created user " + UsersHolder.getUsersMap().get(1).getName());
UsersHolder.addUser(new User(2, "Paul"));
System.out.println("Created user " + UsersHolder.getUsersMap().get(2).getName());
}
public static void main(String[] args) {
UsersCreator.createUsers();
System.out.println("Number of users before notification: " + UsersHolder.getUsersMap().size());
new UsersNotificator().notifyAllUsersButPeters(UsersHolder.getUsersMap());
System.out.println("Number of users after notification: " + UsersHolder.getUsersMap().size());
}
}
And the notificator that notifies all but Peters:
public class UsersNotificator {
public void notifyAllUsersButPeters(final Map<Integer, User> map) {
//we don't need peters, so we'll remove them from the list;
Iterator<Entry<Integer, User>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
if (iterator.next().getValue().getName().equals("Peter")) {
iterator.remove();
}
}
//now we can notify all from the list;
notifyUsers(UsersHolder.getUsersMap());
}
private void notifyUsers(Map<Integer, User> map) {
for (final User user : map.values())
System.out.println("notifyingUsers: " + user.getName());
}
}
Now - the notificator was presented with a map and it may modify it, which it does. It doesn't know that it shouldn't modify it as it's global usersMap. In effect it removes all users with name Peter. It does it for it's own purposes, but the results will be visible for every other class using UsersHolder.
The result is as follows:
Created user Peter
Created user Paul
Number of users before notification: 2
notifyingUsers: Paul
Number of users after notification: 1
When returning unmodifiableMap in UsersHolder the removal will not be possible. The only way would be to create new map with users to notify, so our usersHolder is safe.
This example is a bit big, sorry for that, i failed to think of/create somehting shorter.
Unmodifiable map helps to keep your classes Immutable which is safe(as presented in the example) especially in multithreaded enviroment.
There are many situations in which you do not want your collection to be modifiable. Whenever you know that the collection is initialized with exactly the content it should contain at all times, it can provide security to make it unmodifiable.
The (rather long) example provided by another user is a good example of where it often causes problems. Whenever you traverse a collection, there is a risk you change the collection if you forget to do it on a copy. Making the collection unmodifiable catches and prevents this easy to make mistake.

Hazelcast map synchronization

I am trying to implement distributed cache using Hazelcast in my application. I am using Hazelcast’s IMap. The problem I have is every time I get a value from a map and update the value, I need to do a put(key, value) again. If my value object has 10 properties and I have to update all 10, then I have to call put(key, value) 10 times. Something like -
IMap<Integer, Employee> mapEmployees = hz.getMap("employees");
Employee emp1 = mapEmployees.get(100);
emp1.setAge(30);
mapEmployees.put(100, emp1);
emp1.setSex(“F”);
mapEmployees.put(100, emp1);
emp1.setSalary(5000);
mapEmployees.put(100, emp1);
If I don’t do this way, some other node which operates on the same Employee object will update it and the final result is that the employee object is not synchronized. Is there any solution to avoid calling put explicitly multiple times? In a ConcurrentHashMap, I don’t need to do this because if I change the object, the map also gets updated.
As of version 3.3 you'll want to use an EntryProcessor:
What you really want to do here is build an EntryProcessor<Integer, Employee> and call it using
mapEmployees.executeOnKey( 100, new EmployeeUpdateEntryProcessor(
new ObjectContainingUpdatedFields( 30, "F", 5000 )
);
This way, Hazelcast handles locking the map on the key for that Employee object and allows you to run whatever code is in the EntryProcessor's process() method atomically including updating values in the map.
So you'd implement EntryProcessor with a custom constructor that takes an object that contains all of the properties you want to update, then in process() you construct the final Employee object that will end up in the map and do an entry.setValue(). Don't forget to create a new StreamSerializer for the EmployeeUpdateEntryProcessor that can serialize Employee objects so that you don't get stuck with java.io serialization.
Source:
http://docs.hazelcast.org/docs/3.5/manual/html/entryprocessor.html
Probably a transaction is what you need. Or you may want to take a look at distributed lock.
Note that in your solution if this code is ran by two threads changes made by one of them will be overwriten.
This may interest you.
You could do something like this for your Employee class (simplified code with one instance variable only):
public final class Employee
implements Frozen<Builder>
{
private final int salary;
private Employee(Builder builder)
{
salary = builder.salary;
}
public static Builder newBuilder()
{
return new Builder();
}
#Override
public Builder thaw()
{
return new Builder(this);
}
public static final class Builder
implements Thawed<Employee>
{
private int salary;
private Builder()
{
}
private Builder(Employee employee)
{
salary = employee.salary;
}
public Builder withSalary(int salary)
{
this.salary = salary;
return this;
}
#Override
public Employee freeze()
{
return new Employee(this);
}
}
}
This way, to modify your cache, you would:
Employee victim = map.get(100);
map.put(100, victim.thaw().withSalary(whatever).freeze());
This is a completely atomic operation.
If there is possibility that another node can update data that your node is working with then using put() will overwrite changes made by another node. Usually it is unwanted behavior, cause it leads to data loss and inconsistent data state.
Take a look at IMap.replace() method and other ConcurrentMap related methods. If replace() is failed then you've faced changes collision. In this case you should give it another attempt:
re-read entry from hazelcast
update it's fields
save to hazelcast with replace
After some failed attempts you can throw StorageException to the upper level.
You should use tryLock on your map entry :
long timeout = 60; // Define your own timeout
if (mapEmployees.tryLock(100, timeout, TimeUnits.SECONDS)){
try {
Employee emp1 = mapEmployees.get(100);
emp1.setAge(30);
emp1.setSex(“F”);
emp1.setSalary(5000);
mapEmployees.put(100, emp1);
} finally {
mapEmployees.unlock(100);
}
}else{
// do something else like log.warn(...)
}
See : https://docs.hazelcast.com/imdg/4.2/data-structures/fencedlock#releasing-locks-with-trylock-timeout

Categories