Use of instance variables in java - 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.

Related

How can I replace object in java collection?

I am trying to replace element in collection with new modified version. Below is short code that aims to demonstrate what I'd like to achieve.
The whole idea is that I have one object that consists of collections of other objects. At some point in time I am expecting that this objects in collections (in my example phones) might require some modifications and I'd like to modify the code in one place only.
I know that in order to update the object's attributes I can use setters while iterating through the collection as demonstrated below. But maybe there is better, more general way to achieve that.
public class Customer {
private int id;
private Collection<Phone> phoneCollection;
public Customer() {
phoneCollection = new ArrayList<>();
}
//getters and setters
}
and Phone class
public class Phone {
private int id;
private String number;
private String name;
//getters and setters
}
and
public static void main(String[] args) {
Customer c = new Customer();
c.addPhone(new Phone(1, "12345", "aaa"));
c.addPhone(new Phone(2, "34567", "bbb"));
System.out.println(c);
Phone p = new Phone(2, "9999999", "new name");
Collection<Phone> col = c.getPhoneCollection();
for (Phone phone : col) {
if (phone.getId() == p.getId()) {
// This is working fine
// phone.setNumber(p.getNumber());
// phone.setName(p.getName());
// But I'd like to replace whole object if possible and this is not working, at least not that way
phone = p;
}
}
System.out.println(c);
}
}
Is this possible to achieve what I want?
I tried copy constructor idea and other methods I found searching the net but none of them was working like I would expect.
EDIT 1
After reading some comments I got an idea
I added the following method to my Phone class
public static void replace(Phone org, Phone dst){
org.setName(dst.getName());
org.setNumber(dst.getNumber());
}
and now my foreach part looks like that
for (Phone phone : col) {
if (phone.getId() == p.getId()) {
Phone.replace(phone, p);
}
}
And it does the job.
Now if I change the Phone class attributes I only need to change that method. Do you think it is OK solving the issue that way?
You should not modify the collection while you're iterating through it; that's likely to earn you a ConcurrentModificationException. You can scan the collection for the first object that matches your search criterion. Then you can exit the loop, remove the old object, and add the new one.
Collection<Phone> col = c.getPhoneCollection();
Phone original = null;
for (Phone phone : col) {
if (phone.getId() == p.getId()) {
original = phone;
break;
}
}
if (original != null) {
Phone replacement = new Phone(original);
replacement.setNumber(p.getNumber());
replacement.setName(p.getName());
col.remove(original);
col.add(replacement);
}
Alternatively, you could declare a more specific type of collection, such as a List, that would allow you to work with indexes, which would make the replacement step much more efficient.
If your phone IDs are unique to each phone, you should consider using a Map<Integer, Phone> that maps each phone ID to the corresponding phone. (Alternatively, you could use some sort of third-party sparse array structure that doesn't involve boxing each ID into an Integer.) Of course, if your IDs aren't unique, then you might want to modify the above to gather a secondary collection of all matching phones (and reconsider the logic of your existing code as well).
You can also use a Set (HashSet), this is only when you don't want to do the way Mike suggested.
Use the Phone as an item in the set. Don't forget to implement hashCode() and equals() in Phone. hashCode() should return the id, as it is supposed to be unique.
Since you are concerned about replacing the item, here's how HashSet will help you :
Create an instance of your object.
Remove the object you want to replace from the set.
Add the new object (you created in step 1) back to the set.
Both these operations 2 & 3 are guaranteed in O(1) / constant time.
You don't need to maintain a map for this problem, that's redundant.
If you want to get the object from the collection itself and then modify it, then HashMap would be better, search is guaranteed in O(1) time.
Instead of a list, use a map with the Phone's id as the key. Then your code looks like this:
public static void main(String[] args) {
Customer c = new Customer();
c.addPhone(new Phone(1, "12345", "aaa"));
c.addPhone(new Phone(2, "34567", "bbb"));
System.out.println(c);
Phone p = new Phone(2, "9999999", "new name");
Map<Integer, Phone> phoneMap = c.getPhoneMap();
phoneMap.put(p.getId(), p);
System.out.println(c);
}
If you take the object out from the collection and update its properties, it will get reflected in the same object in collection too.. Hence, you dont have to technically replace object after updating it.
As "Mike M." pointed out, you can use hashmap to retrieve the object quickly without iteration and update the object values.
If order matters to you, you can change Collection to List (Since you're always using an ArrayList anyway) and then:
int index = col.indexOf(phone);
col.remove(phone);
col.add(p, index);

Implementing a static "memory" Map

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.

Calling an Instance method when user inputs the instance name as a String

In a small project I am working on I've gotten stuck. The user enters a command that may be "xp Speed", my command handler class finds that it wants to the XP value of the Speed Instance. In this case it needs to return the value of Skill.Speed.currentXP back to the user.
Small Part of the program:
//Example Instance initialization there is over 40 of these
Skill Speed = (new SkillSpeed(Skills.SKILL_SPEED,Skills.SKILL_SPEED_MODIFIER));
//Constructor for skill class
public Skill(String skillName, double modifier) {
this.name = skillName;
this.minLevel = Skills.MIN_SKILL_LEVEL;
this.Modifier = 1f;
this.currentLevel = (int)calculateLevel();
this.currentXP = 1;
this.leaderboard = getCurrentLeaderboard();
this.ID = getNextID();
}
Now, theres one way i could do this. by having a switch statement with case value being the string entered. However I'm sure having 40+ cases in one switch statement must be avoidable. The other theory I have had is creating a array of all current instances then iterating through that list, finding if the user inputted string is equal to the name of that instance, then returning the instance itself. This is what I came up with:
//method inside another classs that attempts to return the appropriate skill Instance
public Skill getSkillFromName(String Name) {
for(int i = 0; i < Skill.SkillArray.length; i++) {
final String SkillName = Skill.SkillArray[i].getName();
if(SkillName.equalsIgnoreCase(Name)) {
return Skill.SkillArray[i];
}
}
return null;
}
So here's what I need help with:
Creating a array of all initialized instances
Creating the method that will return Skill."InsertRandomInstanceDependingOnUserInputHere".currentXP
Fixing any problems you see in the getSkillFromName() method
Or perhaps I have overlooked a far easier way of doing this, and you can help me with that.
Thanks for the help,
BigDaveNz
If the names of the skills excatly match method names you might find the aswer at "How do I invoke a Java method when given the method name as a string?".
For finding instances by name you can still use Map's.
You can use a Map for this. E.g.:
Map<String, Skill> skills = new HashMap<String, Skill>();
To insert the values you put the values into the Map:
skills.put(skill.getName(), skill);
To retrieve your skill you can get the skill by name:
Skill skill = skills.get(name);

How to create data object dynamically in java?

I am studying data object in Java
I have question for creating the data object dynamically.
For example ,
we have...
public class tasks {
private int vmnumber;
private int tasknumber;
private String status;
public tasks(int vmnumber , int tasknumber , String status) {
this.vmnumber = vmnumber;
this.tasknumber = tasknumber;
this.status = status; }
and there are some getvmnumber gettasknumber , getstatus , and some set functions for
what I understand about creating data object is we have to initialize each time.
for example , in the main file ,
public class task{
public static void main(String [] args){
task t = null , t2 = null;
t = new task();
t.tasknumber = 3;
t.vmnumber = 4;
t.status = "Start";
t2 = new task();
t.tasknumber = 2;
t.vmnumber = 1;
t.status = "Wait";
}
however, i would like to how we can create data object dynamically because program possibly get the information of tasks on real time.(then we can't manually create the data object, we need to something which can create the data object dynamically...)
Second, I would like to know how to get the data from data object.
For example , if we want to find all the information of task number 3 , what should i do ?
lets say , we have task1, task2, task3 data object and we want to see the all information of task1. then what should i do ?
thanks
There are few points to discuss, from your question.
I guess you want to create new tasks, which is maybe a request from the user interace of your application, or a webservice, a batch...
Well, you already know how to create object : with the new keyword. Depending on the original request, your main function may have to create multiple instances of the same class, "Task".
More, when you instantiate the class "Task", you would never want to assign directly values to the properties of it.
So, instead of coding t.tasknumber = 3, you should code : t.setTaskNumber(3)
Also, you should rename the properties of your class to reflect the JavaBeans conventions :
- private int taskNumber instead of tasknumber
Of course, it is only a convention, and it is not mandatory in your program. But it helps generating getters/setters, and, well, it is a convention :-)
To retrieve "information" within your created tasks, you only have to call the getters :
- myTask.getTaskNumber()
Hope this helps you a little bit.

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).

Categories

Resources