How to load data into java program without bloating main method - java

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.

Related

conditions required to make an object polymorphic

What's the difference between a normal object and a polymorphic object in java?
Can someone please explain to me
why Currentaccounts object is polymorphic object or not? if so why?
can someone explain the conditions required to implement polymorphic object?
what is needed to be done to transfer a non polymorphic object to a polymorphic object?
Code sample:
private CurrentAccount CurrentAccounts;
private ISAAccount ISAAccounts;
private SavingAccount SavingAccounts;
public ArrayList<Account> Accounts;
public Customer() {
Filename = "CustomerDetails.txt";
FirstName = "";
LastName = "";
DOB = "01/01/1900";
HomeAddress = new IAddress();
CurrentAccounts = new CurrentAccount(this);
ISAAccounts = new ISAAccount(this);
SavingAccounts = new SavingAccount(this);
Accounts = new ArrayList<>();
}
Polymorphism is the ability of something to have many forms. Or in other words, you can have a class car, which is the general blueprint for all other cars. And then you could have a corvette. Which is still a car, but it also has its own specific characteristics, nonetheless it is still a car, so it could "INHERIT" certain traits from the Car class, while still being its own version of a car. id recommend having a look at some OOP(Object Oriented Programming) lessons to better clarify this for you as it has to do with a lot of different things. Understanding the basics of what Polymorphism and Inheritance are will help you to put everything together in your head.
All object in Java all polymorphic by default. There is no keyword for that like in others languages like "virtual".
So you need nothing to create polymorphic object :)
For example you can have smth like that:
interface Account {}
class CurrentAccounts implements Account {}
class IsAAccounts implements Account {}
class SavingAccounts implements Account {}
so now, you can add to your list
List<Account> accounts = new ArrayList();
all these classes.

Copy content of ArrayList to another with different object

I have two objects who share the same fields: Livre and LivreVO.
How can I copy the content of List<Livre> to List<LivreVO>?
For example:
List<Livre> liste = service.getListeLivre();
List<LivreVO> listeVO = new ArrayList<LivreVO>(liste);
Unless the two classes Livre and Livre0 share a common super-type; you can't (easily).
What you can do:
List<Livre0> listeV0 = new ArrayList<>();
for (Livre livre : service.getListeLivre()) {
Livre0 copy = new LivreV0(...);
listeV0.add(copy);
}
In other words: you have to create new objects; and how you do that depends on your existing classes. A reasonable approach could be to have a constructor within LivreV0 that takes a Livre object; and fetches all relevant properties from there.
Worst case, you might want to look into reflection. That would allow you to basically query all fields in a Livre-Object; and use that information to push values into equally named fields in a Livre0-Object.
Works, but cumbersome and error-prone.
And: it might also be worth stepping back here. Alone the idea of having two different classes that have the same fields ... sounds like a design problem. Thus the real answer might be to rethink your object model. Probably you should have a third class that contains your all those properties that need to be common for Livre and Livre0. Meaning: instead of duplicating all that information, you push that data into Common objects; and then your Livre and Livre0 objects "point" to a Common object.
Let's say that there is a LivreVO constructor which accepts Livre:
LivreVO(Livre object){
// copy common fields.
}
Now we can transform List<Livre> liste into List<LivreVO> listeVO:
List<LivreVO> listeVO = liste.stream().map(LivreVO::new).
collect(Collectores.toList());
Or you can just create new LivreVO objects and populate them manually:
List<LivreVO> listeVO = liste.stream().map(livre -> {
LivreVo tmp = new LivreVo();
tmp.setCommonField(livre.getCommonField());
//...
retrun tmp;
}).collect(Collectores.toList());
You need some mechanism to convert a Livre into a LivreVO, then do something like that:
List<LivreVO> listeVO = new ArrayList<>();
for (Livre l: service.getListeLivre()) {
listVo.add(convert(l));
}

How to read file into Java Object

I don't really understand the logic behind this question and as a result, I can't really accurately search whether something like this already exists.
Let's say I create a Java class for an object. It only consists of instance variables, getters/setters, and a constructor to create an empty object. For example:
public class Bicycle {
private int speed;
private String model;
public Bicycle(int speed, String model) {
this.speed = speed;
this.model = model;
}
public int getSpeed() {
return speed;
}
public void setSpeed() {
this.speed = speed;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
And now let's say I had a text file of bicycles like:
Bike 1234, 60
Bike 333, 50
Bike 555, 20
How would I read the file and then assign each part of the text file to the variables in Bicycle.java?
I want to be able to use the getters and setters in other methods. For example:
public static String searchBikes(int speed, String model) {
if (Bicycle bike.getSpeed().equals(speed) && etc. etc.
I'm unsure as to how to assign each bicycle in the text file to the variables in Bicycle class. Do I need another class (like a database) of sorts? I'm just very lost on this.
Scanner fileScan = new Scanner(new File("yourfile.txt"));
List<Bicycle> bikes = new ArrayList<>();
while(fileScan.hasNextLine()){
String[] line = fileScan.nextLine().split(",");
Bicycle bike = new Bicycle(line[1],line[0]);
bikes.add(bike);
}
Bikes in your file are now in bikes list.
The best approach now a days is java serialization, you can define a human-readable data structure for the bikes and try to convert it to a POJO (plain old java objects), one of the options is using Json format, it es easy t read and there are many APIs for converting strings (son objects to POJO) Gson, Jackson etc etc
a json representation of your file can b:
{
"speed": 33,
"model": 50
}
and with this infomation you can get instances of a class Bicycles, where the attributes model and speed are available as in a "Normal" java object.
take a look at this and this tutorials...
You should read more on "classes and objects" to fully understand what is a CLASS and what is an instance of a class - object.
Oracle's web site can be a good start https://docs.oracle.com/javase/tutorial/java/concepts/
Concerning your concrete problem, well since we talk about object oriented programming, why not just copy the real world model ? Where are bicycles made - in a factory, using a specification of some sort, let's call it a blueprint.
You can create a class called BycicleFactory with a method called "createBycicles(File blueprints)" that returns an ArrayList for example. Here is some more info about the design pattern (best practice) called Factory Design Pattern http://www.tutorialspoint.com/design_pattern/factory_pattern.htm
Inside your factory, you will have to read the file (the blueprint) and create a new Bycicle object per line. I suggest you youse a Scanner, since it is the easiest. http://www.java2s.com/Code/JavaAPI/java.util/newScannerFileReaderfile.htm

MyBatis SelectList Output CopyOnWriteArrayList

Please be patient with the newbie question as I'm trying to learn MyBatis and java at the same time. I have an application in which I need to use threadsafe variables. Based on some research and my ideas of how the application will be used, I've settled on a CopyOnWriteArrayList over a Vector.
When I call a selectList from the mybatis sql session, is there any way to tell it to create an CopyOnWriteArrayList as its return rather than an ArrayList? Admittedly, my code to configure this is two lines instead of one, but something in me says that there's got to be a better way and/or I'm not the first one to have encountered this.
List<Team> teams = session.selectList("getTeamsByGameID", gameID);
List<Team> arrayListReturn = new CopyOnWriteArrayList<Team>(teams);
return arrayListReturn;
Thanks in advance,
I know of two ways to handle this.
Option 1: Use a Mapper class and specify the type of List to return there.
Define a Mapper interface:
public interface TeamMapper {
CopyOnWriteArrayList<Team> getTeamsByGameID();
}
Your mapper xml file stays the same. The code to do the query changes to:
TeamMapper m = session.getMapper(TeamMapper.class);
List<Team> lt = m.getTeamsByGameID();
System.out.println(lt.getClass());
//=> prints out "class java.util.concurrent.CopyOnWriteArrayList"
Option 2: Create a ResultHandler and pass that into the session.select() method.
Here you use the ResultHandler interface. That interface requires you to override one method, handleResult, which is given each result that comes back from the database as the query is in progress.
In your case, your ResultHandler would look something like this:
public class TeamResultHandler implements ResultHandler {
private List<Team> teams = new CopyOnWriteArrayList<Team>();
#Override
public void handleResult(ResultContext rc) {
countries.add((Team) rc.getResultObject());
}
// provide a getter so you can retrieve it when finished
public List<Team> getTeamList() {
return teams;
}
}
Instead of using selectList as you do above, you would now use the session.select(String, ResultHandler), like so:
TeamResultHandler rh = new TeamResultHandler();
session.select("getTeamsByGameID", rh);
List<Team> lt = rh.getTeamList();
return lt;
This solution is more verbose than your solution (requires an extra class and three lines in your query code, rather than 2), but it only creates one List, rather than two, so you'll have to decide which fits your needs best.
In addition, ResultHandlers can be useful for additional things - making sure results are sorted in a certain way or filtered or something else, in case you need that.

Dynamically naming an instance of a class?

Just a really quick question about something small. The following is part of a programming assignment for my programming 2 class. It focuses on inheritance and multiple classes. I've answered the question but want to consolidate the classes into a main function and actually build something rather than just submitting the bare minimum.
My question is the section of code below. The user runs the program, is presented with a dialog asking him as to what he's like to add (a CD or a Movie, they're both separate classes).
What I would like though, is for the user to actually name the specific instance of the class while the program is running. So, the user will click Movie for example, be prompt to enter a name and then next line to use the constructor in the movie class to create a new instance class with the name the user entered? Is this possible? I tried using a simple string x = JOptionpane and then naming the class x also, but it didn't work. I'm thinking there might be some method that will refer to the string? like contents.x maybe?
thanks in advance!
import javax.swing.JOptionPane;
public class Main
{
public static void main (String args [])
{
Object[] options = {"Movie",
"CD",
"Cancel"};
int n = JOptionPane.showOptionDialog(null, "Would you like to add an item?","Product",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[2]);
switch(n)
{
case 0:
String moviet = JOptionPane.showInputDialog("Title:");
int movieID = Integer.parseInt(JOptionPane.showInputDialog("ID:"));
Movie moviett = new Movie(moviet, movieID);
}
}
}
If it's not too far beyond your class' content, you could use a Map<String, Media>1 to store instances identified by a runtime-specified string.
Map<String, Media> instances = new HashMap<>();
// snip...
String moviet = JOptionPane.showInputDialog("Title:");
int movieID = Integer.parseInt(JOptionPane.showInputDialog("ID:"));
Movie moviett = new Movie(moviet, movieID);
instances.put("some user-provided string", moviett);
1Assuming that Movie and CD both extend/implement Media.
Java doesn't work this way, and in fact variable names are much less important than you think and almost don't exist in compiled code. Instead how about using Strings to set a field of the Movie class, perhaps a String field called "name". If you want to retrieve a class instance based on a String, consider using a Map such as a HashMap.

Categories

Resources