Implementing a static "memory" Map - java

I am writing a small application to be used for testing purposes that accepts SOAP calls, generated UID's for each call, and returns this UID. The UID's need to be stored on the server so I thought I'd use a simple static Map to store them.
I created a new class:
MemoryMap.java
public class MemoryMap {
static Map<String, String> memoryMap = new ConcurrentHashMap<String, String>();
static void printMapContents() {
for (Entry<String, String> pair : memoryMap.entrySet()) {
System.out.println("Key = [" + pair.getKey() + "]");
System.out.println("Value = [" + pair.getValue() + "]");
}
}
}
This is then used with the calls:
MemoryMap.memoryMap.put(UID, "testString");
MemoryMap.printMapContents();
and...
MemoryMap.memoryMap.remove(parameters.getUID());
MemoryMap.printMapContents();
This works fine, but I can't think whether this is the recommended way to implement a single Map for this purpose.

If your application must mock a backend, e.g., a database, I recommend abstracting the map away in some datastore interface, and then provide your application with a singleton scoped instance of an implementation of this interface backed by a map. For example:
interface MyDataStore<V>{
V retrieve(UUID id);
void remove(UUID id);
}
public final class MockDataStore implements MyDataStore<String>{
private final static MockDataStore instance = new MockDataStore();
public static MockDataStore instance(){
return instance;
}
private MockDataStore(){}
private final ConcurrentHashMap<UUID,String> m =
new ConcurrentHashMap<UUID,String>();
#Override
String retrieve(UUID id){
return m.get(id);
}
#Override
void remove(UUID id){
m.remove(id);
}
}
Then tomorrow you can swap the implementation for something that speaks to an actual database. This is a very rough approximation of an ORM system.
Even better, I would start with a database right off the bat. You could use an in memory database (like H2) so that you could replace it with an actual database (with possibly some minor migration issue) when you need to.
Finally, if your storage needs grow, e.g., you need tables and relations among them, I recommend looking at JPA and one of its implementations, e.g., Hibernate.

Your server accepts SOAP requests, most likely this is done in several threads. ConcurrentHashMap should work just fine.

Related

Use of instance variables in java

I have a method called getCustomerCount() which makes a database call to get the customer count based on the store like below.
public int getCustomerCount(String storeName) {
return repository.getCustomerCount(storeName);
}
I need to call the above method more than once from other methods so can I use an instance variable to set the customer count the very first time this method gets called and then reuse the variable instead of calling this method and making a database call every single time? Can I do something like this:
private int customerCount;
public int getCustomerCount(String storeName) {
int count = repository.getCustomerCount(storeName);
customerCount = count;
return count;
}
public void processCustomerData(String storeName) {
getCustomerCount(storeName);
// Based on customer count, add business logic
sendEmail(customerList);
}
public void sendEmail(List<Customers> customers) {
// get customer count and set email count to the number of customers in the system.
int emailCount = 0;
emailCount = customerCount;
}
Would this be an issue when multiple requests execute at the same time through a rest api? Are there any pros and cons of using instance variables like this? If there are better ways than using instance variables, please suggest. I need to execute the query for each request so singleton may not work for this case. Thank you.
You could try to use the singleton design pattern for your specific problem
See this link: https://www.gofpatterns.com/creational/patterns/singleton-pattern.php
I assume code above you shared is customerService. SpringBoot is singleton, so it is not good practice to have global variables(if they are not constant) in SpringBoot objects.
#Service
private CustomerService customerService;
int customerCount = customerService.getCustomerCount();
customerService.processCustomer(customerCount); // you should pass customerCount
Also you should change sendEmail method as it should take customerCount as argument if customers size can be different from customerCount
public void sendEmail(List<Customers> customers, int customerCount)
If you don't want the method to hit the database each time, you should use the Integer wrapping class and store the count in a map:
private Map<String, Integer> customerCountMap = new HashMap();
public int getCustomerCount(String storeName) {
if(customerCountMap.get(storeName) == null) {
// you will probably need to pass the store name to the repository...
customerCountMap.put(storeName, repository.getCustomerCount(storeName));
}
return customerCountMap.get(storeName);
}
You still need to update the count on Insert and delete. So you might end up with Spring caching anyway (or you could use the old fashioned observer pattern).
The sendEmail() method still doesn't make sense.

How can I make a java table where all rows can be used as keys?

This is hard for me to explain as I'm not native to the English language, so I will try setting up an example.
I am trying to save some data about a player in a class called PlayerData. It has three variables with getters and setters.
public class PlayerData {
private String player;
private String username;
private UUID uuid;
public String getPlayer() {
return player;
}
public void setPlayer(String player) {
this.player = player;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
}
For each player in the game, there will be generated a PlayerData object. Normally I would store this in a Map, so I can get the data about a player from eg. the UUID. However, I could use a way to be able to use any variable in the PlayerData object as "key", so I don't require the UUID to get the PlayerData. A way to do this (and my usual approach) would be to have multiple maps, something like this.
Map<String, PlayerData> playerMap;
Map<String, PlayerData> usernameMap;
Map<UUID, PlayerData> uuidMap;
The problem is, when it scales up with multiple variables, this gets annoying, and perhaps even eats up the RAM? I'm not entirely sure, as it stores references.
It similar to SQL, where you can also get specific colums based on the content of the rows. That's what I'm looking for, but without the SQL database.
I made a table explanation below in an attempt to explain it further:
Player
Username
UUID
Peter
Peter1234
657f6c48-655f-11eb-ae93-0242ac130002
Stephen
DogLover69
657f6efa-655f-11eb-ae93-0242ac130002
Joshua
XxFlowerPotxX
657f6fea-655f-11eb-ae93-0242ac130002
Short edition
I'm looking for a way to store multiple objects of the same type, where I (unlike Maps, that only take a single object as Key) can use multiple assigned variables as keys.
I hope the explaination was clear, I have absoloutly no idea how to explain it, which is probably also why I can't solve it by googling.
Thank you for your time.
As far as I understand, it's need to store various data for a specific user (and not just to update old values)
One way is through a custom map. Since only need a key (unique), could assume that username is doing that (eg:login). MyData can be customized further with what ever wanted to store.
Each key/username will contain a distinct list where new data is added.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class TestPData {
public static void main(String[] args)
{
TestPData t = new TestPData();
MyMap m = t.new MyMap();
//key can be just user name, if unique is assured
m.putMyData("player_1", t.new MyData("p1_data1"));
m.putMyData("player_1", t.new MyData("p1_data2"));
m.putMyData("player_2", t.new MyData("p2_data3"));
m.putMyData("player_3", t.new MyData("p2_data4"));
m.putMyData("player_3", t.new MyData("p2_data5"));
m.putMyData("player_3", t.new MyData("p2_data6"));
m.forEach((k,v)->{for(MyData d: v) {System.out.println(k+":"+d);}});
}
class MyData
{
String s;
public MyData(String s)
{
this.s = s;
}
public String toString()
{
return s;
}
}
class MyMap extends HashMap<String, List<MyData>>
{
private static final long serialVersionUID = 1L;
public void putMyData(String k, MyData d)
{
if(!this.containsKey(k))
{
this.put(k, new ArrayList<MyData>());
this.get(k).add(d);
}
else
{
this.get(k).add(d);
}
}
}
}
Output
player_1:p1_data1
player_1:p1_data2
player_3:p2_data4
player_3:p2_data5
player_3:p2_data6
player_2:p2_data3
If you are dealing with few records (some thousands), you can use a list and iterative search as suggested by #gilbert-le-blanc, but if you need to manage huge amounts of records/attributes, it is better to use a database anyway. You can also use an in-memory database like Derby or H2.
https://www.h2database.com/
https://db.apache.org/derby/
With some effort you can create a custom collection with multi-indexed properties also, but it is not worth the pain.
I would use a map of maps, with the first mapping by the name of the property and the second map by its value.
In code:
Map<String, Map<String, PlayerData>> index = new HashMap<>();
To add a mapping:
PlayerData peterData = new PlayerData(
"Peter",
"Peter1234",
"657f6c48-655f-11eb-ae93-0242ac130002");
index.computeIfAbsent("player", k -> new HashMap<>())
.put("Peter", peterData);
index.computeIfAbsent("username", k -> new HashMap<>())
.put("Peter1234", peterData);
index.computeIfAbsent("uuid", k -> new HashMap<>())
.put("657f6c48-655f-11eb-ae93-0242ac130002", peterData);
This navigates to the different inner maps (one per indexed property) by means of the Map.computeIfAbsent method, which creates an empty inner map and puts it into the outer map if it doesn't exist, or returns it if already present. Then, we add the mapping to the inner map by using Map.put as usual.
To remove a mapping:
index.computeIfAbsent("username", k -> new HashMap<>()).remove("Peter1234");
This is completely dynamic, as you don't have to change the data structure when you need to map by more properties. Instead, all you have to do is add mappings as needed.
The downside of this approach is that you'd need to use strings for the keys of the inner maps, but I think this is a reasonable trade-off.

What data structure should I use for object storage, for easily generating primary keys for new entries?

I'm doing a school project in Java and I the following question have arisen:
I have an entity with attributes - id, name, phone.. with id as the unique primary key. I want to store them in a data structure(such as list..). Then in the application I obtain the data for creating a new instance (name, phone..) and I want to create a new instance of the entity and store it in my data structure with a new unique id. The id shouldn't be random, it would be best if the id rised continuously with the size of the list. Also I dont want to reuse ids.
The first implementation that comes to my mind is to use ArrayList and simply set id as indexes. But ArrayList.remove(int index) after removal shifts all following elements to left. I assume that ArrayList.remove(Object o) works the same, but i would be gratefull i I'm proven wrong. Determining ids from last element would not work either. I could go through all of them but that seems inefiicient.
Thanks in advance for any help :)
You want to keep a counter for them. You could use a static value in the class (you may need to synchronize it for multi-threaded classes.)
import java.util.concurrent.atomic.AtomicInteger;
class MyClass {
// thread safe
private static final AtomicInteger safeCounter = new AtomicInteger();
private final int uniqueId; // can never change uniqueId
private String name; // the data of the class
public MyClass(String name) {
this.name = name;
this.uniqueId = MyClass.safeCounter.getAndIncrement();
}
public boolean equals(Object o) {
if(o instanceof MyClass) { // instanceof also does null check :-)
MyClass mc = (MyClass)o;
return mc.uniqueId == this.uniqueId;
}
return false;
}
public int hashCode() {
return uniqueId;
}
}
If this is for homework, or if threadsafety isn't a concern, you can use a simple static int
class MyClass {
private static int nextUniqueId() {
int result = counter;
counter++;
return result;
}
// not thread safe
private static int counter;
private final int uniqueId; // can never change uniqueId
private String name; // the data of the class
public MyClass(String name) {
this.name = name;
this.uniqueId = nextUniqueId();
}
public boolean equals(Object o) {
if(o instanceof MyClass) { // instanceof also does null check :-)
MyClass mc = (MyClass)o;
return mc.uniqueId == this.uniqueId;
}
return false;
}
public int hashCode() {
return uniqueId;
}
}
How about using a Factory that users a Strategy for generating your identifiers?
Edited to answer question about factories
A Factory is a design pattern that is used to encapsulate the creation of different types of Objects. A Strategy is another design pattern that is used to encapsulate the behavior of specific business logic that might have different rules or that might change over time.
In your case you clearly require a new Identifier for each object that needs to be unique. You also stated in your question comments above that eventually you will be storing your objects in a database, which also would most likely require you to get your identifier from your database in the long run.
Here is a smallish example of using a Factory to create your User Objects instead of just using new(). Please kindly disregard any spelling or compile mistakes, I wrote the following code with out the assistance of a compiler or IDE.
public interface UserFactory {
User createUser();
}
public interface IdentifierStrategy {
// I just picked Long for ease of use.
Long getIdentifier();
}
public class UserFactoryImpl {
private final IdentifierStrategy identifierStrategy;
public UserFactoryImpl(final IdentifierStrategy identifierStrategy) {
this.identifierStrategy = identifierStrategy;
}
public User createUser() {
Long identifier = this.identifierStrategy.getIdentifier();
User user = new User(identifier);
return user;
}
}
public class LongIdentifierStrategy implements IdentifierStrategy {
public Long getIdentifier() {
// Do something here that will return a unique long.
Long long = new Long(1);
return long;
}
}
// In the long term, you would most likely use this IdentiferStrategy
// to get your identifiers from the database.
public class JDBCIdentifierStrategy implements IdentifierStrategy {
public Long getIdentifer() {
// Get a jdbc connection from a jdbc connection pool.
// Get the next identifier from the databsae.
Long long = new Long(1);
return long;
}
}
Now, in the long run, if your requirement change for how you need to identifier your User objects, you would only need to write a new IdentifierStrategy and update your UserFactoryImpl with that new Strategy.
One important question: what's the scope of the uniqueness?
Just for the duration of a run of the application? Do you have a single thread or multiple threads, so unique across those threads? Or could there be several copies of the app running at the same time, so unique across all instances, even across many machines? Will you save the data somewhere and so need uniqueness across future runs of the program too?
Two fundamental schemes:
a). use a database, they usually offer some kind of auto-generated primary key: you insert the record, it gives you a unique key.
b). generate the key yourself, in this case: first isolate the key generation to it's own class, then you can make the generation as clever as you wish. Sketch:
some initialisation, generate an initial value, simple case it's zero, or it derives from the current date/time, or MAC address of your machine, or whatever
provide a getNextId() function, which probably needs to be synchronized if threads are involved.
A very simple scheme, which will be OK for low volume systems, just use
new Date().getTime();
You can also look for GUID generators, which produce something unique, but rather bigger than an int.
My suggestion is to have an Object Pooling for ID generation. When the entity is "deleted", the ID should be returned to the pool, and when needing a new ID, the pool should either
Give you a new ID (if old ID doesn't exists in pool) or
Create a new ID for an entity.
The problem is that you will have to create an entity management system that caters for returning the "used" ID to the pool if entity is "deleted" (bear in mind the multithreading environment, which you will need to manage).
Alternatively, use a database system which provides primary key generation (most uses AUTO_INCREMENT).

How to build a complex, hierarchic immutable data structure in Java?

I'm building a Java library for a customer, and one of the things they want is a data representation of a particular set of standards they work with. I don't want to reveal my customer's interests, but if he were an alchemist, he might want the following:
Elements
Fire
Name="Fire"
Physical
Temperature=451
Color="Orange"
Magical
Domain="Strength"
Water
Name="Water"
Physical
Color="Blue"
Earth
Name="Earth"
Magical
Domain="Stability"
Ordinality=1
I need to be able to access various data elements by name, such as:
Elements.Earth.Name
Elements.Water.Physical.Color
I also need to be able to iterate through attributes, as:
for (MagicalType attrib : Elements.Fire.Magical)
{
...
}
I have actually been able to create this data structure, and I can do everything I've asked for above -- though I had to create separate arrays for the iteration, so really what I do looks more like:
for (MagicalType attrib : Elements.Fire.MagicalAuxArray)
Unfortunately I haven't been able to meet my last requirement: the entire data structure must be immutable. I have tried repeatedly, and scoured the web looking for examples, but so far I haven't been able to accomplish this in any reasonable manner. Note that the final data structure will be quite large; I'm really hoping to avoid a solution that is too repetitious or creates too many public symbols.
I am a very experienced programmer, less experienced with Java. Can anyone suggest how I might represent the above data to meet all my requirements?
A few ways that come to mind immediately:
Don't provide setter methods for your object. You users can only create the object via a constructor and once created, it cannot be modified. This goes for other state-modification methods as well. If you want to avoid a very large parameter-list in your constructor, you can use the Builder pattern (described in Effective Java by Joshua Bloch (2nd Ed))
When returning collections, make defensive copies. In this case use a List instead of an array. That way you can do return new ArrayList<MagicalType>(MagicalAuxList) instead of return MagicalAuxList. This way people who use the class won't be able to modify the collection. One caveat here. If your array contains complex objects, they must be immutable as well.
For immutable collections, you can also try using the unmodifiableCollection static method (there are similar static-methods for lists, sets, etc. - use whichever one is appropriate for you) to convert your collection when you return it. This is an alternative to defensive copying.
Why do you use arrays? Wouldn't immutable collections (e.g. from Google Guava) do a better job?
You can use Iterable in your public API. Cleaner than Collections with all the mutators that you have to suppress. (unfortunately Iterator has a remove() method(?!) but that's just one)
public final Iterable<MagicalType> magics;
for(MagicalType magic : magics) ...
you could try the code below that uses final, enums and unmodifiable maps. but that does not let you access by name since you need to do a get from the map. you could probably do that in groovy.
import java.util.*;
enum Color {
red, green, blue;
}
class Physical {
Physical(final Double temperature, final Color color) {
this.temperature = temperature;
this.color = color;
final Map<String, Object> map=new LinkedHashMap<String, Object>();
map.put("temperature", temperature);
map.put("color", color);
this.map=Collections.unmodifiableMap(map);
}
final Double temperature;
final Color color;
final Map<String, Object> map;
}
class Magical {
Magical(final String domain, final Integer ordinality) {
this.domain = domain;
this.ordinality = ordinality;
final Map<String, Object> map=new LinkedHashMap<String, Object>();
map.put("domain", domain);
map.put("ordinality", ordinality);
this.map=Collections.unmodifiableMap(map);
}
final String domain;
final Integer ordinality;
final Map<String, Object> map;
}
public enum Elements {
earth("Earth", new Magical("Stability", 1), null), air("Air", null, null), fire("Fire", new Magical("Strength", null), new Physical(451., Color.red)), water(
"Water", null, new Physical(null, Color.blue));
Elements(final String name, final Magical magical, final Physical physical) {
this.name = name;
this.magical = magical;
this.physical = physical;
}
public static void main(String[] arguments) {
System.out.println(Elements.earth.name);
System.out.println(Elements.water.physical.color);
for (Map.Entry<String, Object> entry : Elements.water.physical.map.entrySet())
System.out.println(entry.getKey() + '=' + entry.getValue());
for (Map.Entry<String, Object> entry : Elements.earth.magical.map.entrySet())
System.out.println(entry.getKey() + '=' + entry.getValue());
}
final String name;
final Magical magical;
final Physical physical;
}

Simulate named parameters in Java

I write a little web API which should it make easy to create URIs. Each resource class should contain a method createURI which takes the needed parameters. This method should use a helper method, populateUriTemplate, in the background to create an URI string. populateUriTemplate needs key value pairs to populate an URI template. In another language like Scala or Python I would use named parameters, but Java doesn't support them. So the question is: How to simulate named parameters in Java?
The straight forward solution would be to create a map:
public String createUri(int id, String name){
Map<String, Object> params = new HashMap<String, Object>();
params.put("id", id);
params.put("name", name);
return populateUriTemplate(params);
}
But I don't like to create a map first and put each parameter to it.
Another idea is to use a static method, param, to create key value pairs:
public String createUri(int id, String name){
return populateUriTemplate(param("id", id), param("name", name));
}
Looks much better to me!
It could be refined a bit to make it more self-explanatory, even if a few more characters are needed:
public String createUri(int id, String name){
return populateUriTemplate(key("id").value(id), key("name").value(name));
}
I've also thought of the builder pattern, but this would force the user of my API to create an explicit builder for each resource class, what would be tedious without a benefit. The type of the parameter is not important, as long as a proper implemented toString method exists.
My favourite is one of the both approaches with the static methods above (param(key, value) or key(k).value(v)). Do you know a better way to simulate named parameters in this case?
For some ideas on the builder pattern, you could see this blog post by Stephan Schmidt.
You also just gave me the idea to do the following, with fluent interfaces, a Callable, and a static method:
createUri().id(5).name("dennetik").call();
Which would require createing a Callable class (CreateUri) with the static method:
public static final CreateUriFluentInterface createUri() {
return FluentInterface.of(new CreateUri(), CreateUriFluentInterface.class);
}
And a fluent interface, like this:
public interface CreateUriFluentInterface {
public CreateUriFluentInterface id(Integer id);
public CreateUriFluentInterface name(String name);
}
Which isn't that much boilerplate code, is it?
(Well, if you tone down that horribly named CreateUriFluentInterface a bit, it isn't.)
(You would probably have CreateUriFluentInterface extend Callable<String>, to be able to reroute the call to Callable#call())
populateUriTemplate("id",id, "name",name);
void populateUriTemplate(Object... nvs){
for(int i=0; i<nvs.length/2; i++)
....
}
Maybe you like this approach:
class Params {
private HashMap<String, Object> allParams = new HashMap<String,Object>();
public Params(ParamEntry...params) {
for( ParamEntry p : params ) {
allParams.put(p.name, p.value);
}
}
public getParam(String name) {
return allParams.get(name);
}
class ParamEntry {
public String name;
public Object value;
}
}
public String createUri(Params.ParamsEntry ... params){
return populateUriTemplate(new Params(params));
}
To call it use
createUri(new Param.ParamEntry("name", valueObject) );
Inside the populateUriTemplate...
just use params.get("name");
Spring MVC does exactly this. As well as being able to bind requests to specific methods in controller classes, you can bind request parameters to method parameters. You can have a look to see how it works, but basically it picks a strategy to map the right request parameter to the right method parameter.
You basically get something like:
public String createUri(#RequestParam int id, #RequestParam String name){
return populateUriTemplate(id, name);
}
This is almost silly and slightly off topic, but using Lombok's #Builder annotation takes this closer to the desired result.
Furthermore if the builder, builder method and build method names are changed to _ they almost disappear:
import static foo.Template._;
class Resource {
String createURI(String id, String name) {
return populateURITemplate(_.id(id).name(name)._());
}
String populateURITemplate(Template t ){
return t.id+"="+t.name;
}
}
#Builder(builderClassName = "_", builderMethodName = "_", buildMethodName = "_" )
class Template {
static _ _ = _();
String id;
String name;
}
Named parameters are not the way:
Named parameters do not make your code any cleaner in this case. I would argue that they make things more complex and error prone in Java because you lose type safety and you lose compiler warnings about identifiers that do not exist.
TypeSafe Immutable Fluent Builders:
I wrote an article on a UrlBuilder implementation earlier this year, it shows a type safe fluent interface that enforces order of construction for mandatory input and allows for optional parts with sane defaults as well.
Now I will be the first to admit that the approach I use is fairly verbose, but it is extremely productive once that initial price is paid. It works with dependency injection and is easily unit testable and most importantly is composable for specialization.
final URL url1 = new UrlBuilder().scheme("http").host("www.google.com").build();
System.out.println("url1 = " + url1);
final URL url2 = new UrlBuilder().scheme("https").userInfo("xkcd", "correcthorsebatterystaple").host("admin.xkcd.com").build();
System.out.println("url2 = " + url2);
Produces:
url1 = http://www.google.com
url2 = https://xkcd:correcthorsebatterystaple#admin.xkcd.com
I am addressing the verbosity of the anonymous inner class implementations of the interfaces with another approach I am experimenting with; type safe implementations of value objects from interfaces using dynamic proxies.
This will do away with the boilerplate value objects and replace them with Map<String,?> but put a dynamically generated type safe immutable Interface wrapper around them.
I encourage you to read about both of these and see how combining them gives you a better solution than named properties ever would.
When I get time to refactor my UrlBuilder with the dynamic proxies I will post another blog post about it as well.
Named Parameters via Guice
If you are dead set on named parameters then I would recommend looking at Guice #Named bindings. You still lose the compile type checks and safety but at least you get some validations from Guice.
public class RealBillingService implements BillingService {
#Inject
public RealBillingService(#Named("Checkout") CreditCardProcessor processor,
TransactionLog transactionLog) {
...
}

Categories

Resources