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.
Related
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.
I have a method that takes in a JSON and takes out the data and distributes it to various strings so that they can be set in an entity and persisted. My example below is quite simple but for my actual code I have about 20+ fields
For example see
public Projects createProject(JsonObject jsonInst) {
Projects projectInst = new Projects();
String pId = jsonInst.get("proId").getAsString();
String pName = jsonInst.get("proName").getAsString();
String pStatus = jsonInst.get("proStatus").getAsString();
String pCustId = jsonInst.get("proCustId").getAsString();
String pStartDate = jsonInst.get("proStartDate").getAsString();
...
//Set the entity data
projectInst.setProjectId(pId);
projectInst.setProjectName(pName);
...
Notice if a varible dosent have a corrosponding entry in the Json this code will break with null pointer exception. Obviously I need to validate each parameter befopre calling .getAsString()
What is the best way to do this from a readability point of view I could create 2 varibles for each parameter and check and set for example.
if(jsonInst.get("proName")){
String pName = jsonInst.get("proName").getAsString();
}
Or should I wait for it to be set
if(!pName.isEmpty()){
projectInst.setName(pName)
}
...
Which of these do you think is the best parameter to use for preventing errors.
Is there a way to handle if something is set on a large scale so that I can reduce the amount of code I have to write before I use that varible?
You can create a method that will take field name as parameter and will return json value for that field :
private String getJSONData(String field,JsonObject json){
String data=null;
if(json.has(field)){
data=json.get(field).getAsString();
}
return data;
}
you can call this method for each of your field:
String pId = getJSONData("proId",jsonInst);
By this way you can not only escape NullPointerException, but also avoid code repetition.
I'm looking for some object oriented design help basically.
At the start of my program I need to load a whole bunch of data into the program(not from a database or anywhere; in this case I'm just loading it into the program) by building objects and assigning variables. However this takes up a lot of room and I feel like I'm just clogging up the main method and making it unreadable.
I'm wondering what's the right way to approach this is, as far as OOP goes.
I tried to make a class SubjectBuilder, and create everything in the constructor or variable space, and then create a new object in the main method. But it seems that alldata is out of the scope of the main method so when I need to manipulate it later I can't.
Student jack = new Student("Jack Smith"); // Creating all the Student objects
Student jim = new Student("Jim Lucas");
Student beck = new Student("Beck Barber");
Student ann = new Student("Ann Walker");
Student lucy = new Student("Lucy Boxer");
Subject maths = new Subject("Maths"); // Creating all the Subject objects
Subject business = new Subject("Business");
Subject java = new Subject("Java");
Subject design = new Subject("Design");
Subject project = new Subject("Project");
business.addStudent(jack, 70);
business.addStudent(jim, 65);
business.addStudent(beck, 70);
business.addStudent(ann, 83);
business.addStudent(lucy, 78);
^^ That's a snippet data I need to load. I have a bunch of marks for each subject.
At this stage I only have the Application class, Subject class (HashMap of student and Integer mark), and Student.
All I need to do is create this program that displays individual data for students or subjects and allows changes to particular marks etc. I'm confident I could complete the whole project in the main method but I feel like that's not very object oriented. I just don't know how to do it otherwise.
Firstly, how about creating a method to do this so it is not in your main
e.g.
Class MyClass {
public void main (String args[]) {
myClass mc = new MyClass();
mc.loaddata ();
}
private void loadData () {
}
Now in your loadData method you could load this data from a CSV file maybe? See http://opencsv.sourceforge.net/
A simple suggestion for: create a StudentFactory to encapsulate students instantiation, the facory method might looks like: public List createAllStudents();
And the same to Subject class.
If you are only going to access the students from the business class you could do the following
business.addStudent(new Student("Jack Smith"), 70);
business.addStudent(new Student("Jim Lucas"), 65);
business.addStudent(new Student("Beck Barber"), 70);
business.addStudent(new Student("Ann Walker"), 83);
business.addStudent(new Student("Lucy Boxer"), 78);
Keep your data in arrays or some other data structure like
String names = {"Jack Smith","John","Asley"};
int grades = {70,65,85}; //you can generate local or global array , its up to you
int main()
{
for(int i=0;i<names.length;i++)
business.load(names[i],grades[i]);
}
//Do your work in load method
You should use a map to hold your students, and use Long or String or any other immutable class as your key. I recommend using a Map because it's O(1) to access data from this kind of collection, against O(n) if you use, for instance, an ArrayList<Students>.
private Map<Long, Student> students = new HashMap<>();
Then you should move your loading data to a method such as:
private void loadStudents(){
student.put(1L , new Student("Jack Smith"));
student.put(2L , new Student("Joe Doe"));
student.put(3L , new Student("Jane Doe"));
}
For your Subject you could use again some map:
private void loadSubjects(){
subjects.put("MATH" , new Subject("Mathematics"));
subjects.put("JAVA" , new Subject("Java"));
subjects.put("DESING_PATTERNS" , new Subject("DesingPatterns"));
//for instance you could have more advanced subjects such as:
subjects.put("C++" , new Subject("C++" , "lecture" , "class 101" , "prof. T. Richards"));
}
Since by calling an object's constructor means that that object is ready for use, you should call your loadStudent() (and possibly loadSubjects() method, or any methods you use to load your data into the application) into this constructor.
public BusinessLogic(){
loadStudents();
loadSubjects();
//and so on
}
This is the prefered way against having to call load data methods on your newly created object, and always remembering you have to call these methods before using your object:
BusinessLogic business = new BusinessLogic();
business.calculateFinalGrades(); // NOT GOOD BECAUSE YOU HAVE FORGOTTEN TO CALL loadStudents();
So, you'll end up having something like:
public static void main(String[] args){
buildUI();//build your command line interface / graphical user interface
BusinessLogic businessLogic = new BusinessLogic();//you can probably now make this object a Singleton in order to prevent having multiple instances
...
}
You are right, building the whole application in the main is not the way to do it. In my opinion you should build a class that provides data let's say DataProvider that has methods for providing given data. As there are multiple ways of storing data, you can make this an interface/ abstract class depending on the common code. As your project can evolve and later maybe you want to extract data from DB or XML or something else. Like this it will be loose coupled and easy to replace. It might look like this:
interface DataProvider<T> {
Collection<T> loadData();
//...other useful methods
}
class DummyStudentDataProvider implements DataProvide<Student> {
Collection<Student> loadData() {
///...your logic
}
}
I used generics as the same logic could be used for different classes that you might need. Hope this helps you.
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);
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).