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));
}
Related
In my application, I have to instantiate many different types of objects. Each type contains some fields and needs to be added to a containing type. How can I do this in an elegant way?
My current initialization step looks something like this:
public void testRequest() {
//All these below used classes are generated classes from xsd schema file.
CheckRequest checkRequest = new CheckRequest();
Offers offers = new Offers();
Offer offer = new Offer();
HotelOnly hotelOnly = new HotelOnly();
Hotel hotel = new Hotel();
Hotels hotels = new Hotels();
Touroperator touroperator = new Touroperator();
Provider provider = new Provider();
Rooms rooms = new Rooms();
Room room = new Room();
PersonAssignments personAssignments = new PersonAssignments();
PersonAssignment personAssignment = new PersonAssignment();
Persons persons = new Persons();
Person person = new Person();
Amounts amounts = new Amounts();
offers.getOffer().add(offer);
offer.setHotelOnly(hotelOnly);
room.setRoomCode("roomcode");
rooms.getRoom().add(room);
hotels.getHotel().add(hotel);
hotel.setRooms(rooms);
hotelOnly.setHotels(hotels);
checkRequest.setOffers(offers);
// ...and so on and so on
}
I really want to avoid writing code like this, because it's a little messy having to instantiate each object separately and then initialize each field across multiple lines of code (e.g. having to call new Offer() and then setHotelOnly(hotelOnly) and then add(offer)).
What elegant methods can I use instead of what I have? Are there any "Factories" that can be used? Do you have any references/examples to avoid writing code like this?
I'm really interested in implementing clean code.
Context:
I'm developing a RestClient Application for sending post requests to a Webservice.
The API is represented as a xsd schema file and I created all the Objects with JAXB
Before sending a request I have to instantiate many Objects because they have dependencies with each other.
(An Offer has Hotels, a Hotel has Rooms, a Room has Persons... And these Classes are the generated ones)
Thanks for your help.
You can either use a constructor or a builder pattern or a variation of the builder pattern to fix the problem of having too many fields in your initialization step.
I'm going to extend your example a bit to prove my point of why these options are useful.
Understanding your example:
Lets say an Offer is simply a container class for 4 fields:
public class Offer {
private int price;
private Date dateOfOffer;
private double duration;
private HotelOnly hotelOnly;
// etc. for as many or as few fields as you need
public int getPrice() {
return price;
}
public Date getDateOfOffer() {
return dateOfOffer;
}
// etc.
}
As it stands in your example, to set values to these fields, you use setters:
public void setHotelOnly(HotelOnly hotelOnly) {
this.hotelOnly = hotelOnly;
}
Unfortunately, this means if you need an offer with values in all of the fields, you have to do what you have:
Offers offers = new Offers();
Offer offer = new Offer();
offer.setPrice(price);
offer.setDateOfOffer(date);
offer.setDuration(duration);
offer.setHotelOnly(hotelOnly);
offers.add(offer);
Now let's look at improving this.
Option 1: Constructors!
A constructor other than the default constructor (the default constructor is currently Offer() ) is useful for initializing the values of the fields in your class.
A version of Offer using constructors would look like this:
public class Offer {
private int price;
private Date dateOfOffer;
//etc.
// CONSTRUCTOR
public Offer(int price, Date dateOfOffer, double duration, HotelOnly hotelOnly) {
this.price = price;
this.dateOfOffer = dateOfOffer;
//etc.
}
// Your getters and/or setters
}
Now, we can initialize it in one line!
Offers offers = new Offers();
Offer offer = new Offer(price, date, duration, hotelOnly);
offers.add(offer);
Even better, if you never use offer other than that single line: offers.add(offer); you don't even need to save it in a variable!
Offers offers = new Offers();
offers.add( new Offer(price, date, duration, hotelOnly) ); // Works the same as above
Option 2: Builder Pattern
A builder pattern is useful if you want the option of having default values for any of your fields.
The problem a builder pattern solves is the following messy code:
public class Offer {
private int price;
private Date dateOfOffer;
// etc.
// The original constructor. Sets all the fields to the specified values
public Offer(int price, Date dateOfOffer, double duration, HotelOnly hotelOnly) {
this.price = price;
this.dateOfOffer = dateOfOffer;
// etc.
}
// A constructor that uses default values for all of the fields
public Offer() {
// Calls the top constructor with default values
this(100, new Date("10-13-2015"), 14.5, new HotelOnly());
}
// A constructor that uses default values for all of the fields except price
public Offer(int price) {
// Calls the top constructor with default values, except price
this(price, new Date("10-13-2015"), 14.5, new HotelOnly());
}
// A constructor that uses default values for all of the fields except Date and HotelOnly
public Offer(Date date, HotelOnly hotelOnly) {
this(100, date, 14.5, hotelOnly);
}
// A bunch more constructors of different combinations of default and specified values
}
See how messy that can get?
The builder pattern is another class that you put inside your class.
public class Offer {
private int price;
// etc.
public Offer(int price, ...) {
// Same from above
}
public static class OfferBuilder {
private int buildPrice = 100;
private Date buildDate = new Date("10-13-2015");
// etc. Initialize all these new "build" fields with default values
public OfferBuilder setPrice(int price) {
// Overrides the default value
this.buildPrice = price;
// Why this is here will become evident later
return this;
}
public OfferBuilder setDateOfOffer(Date date) {
this.buildDate = date;
return this;
}
// etc. for each field
public Offer build() {
// Builds an offer with whatever values are stored
return new Offer(price, date, duration, hotelOnly);
}
}
}
Now, you can not have to have so many constructors, but still are able to choose which values you want to leave default, and which you want to initialize.
Offers offers = new Offers();
offers.add(new OfferBuilder().setPrice(20).setHotelOnly(hotelOnly).build());
offers.add(new OfferBuilder().setDuration(14.5).setDate(new Date("10-14-2015")).setPrice(200).build());
offers.add(new OfferBuilder().build());
That last offer is simply one with all default values. The others are default values except the ones that I set.
See how that makes things easier?
Option 3: Variation of Builder Pattern
You can also use the builder pattern by simply making your current setters return the same Offer object. It's exactly the same, except without the extra OfferBuilder class.
Warning: As user WW states below, this option breaks JavaBeans - a standard programming convention for container classes such as Offer. So, you shouldn't use this for professional purposes, and should limit your use in your own practices.
public class Offer {
private int price = 100;
private Date date = new Date("10-13-2015");
// etc. Initialize with default values
// Don't make any constructors
// Have a getter for each field
public int getPrice() {
return price;
}
// Make your setters return the same object
public Offer setPrice(int price) {
// The same structure as in the builder class
this.price = price;
return this;
}
// etc. for each field
// No need for OfferBuilder class or build() method
}
And your new initialization code is
Offers offers = new Offers();
offers.add(new Offer().setPrice(20).setHotelOnly(hotelOnly));
offers.add(new Offer().setDuration(14.5).setDate(new Date("10-14-2015")).setPrice(200));
offers.add(new Offer());
That last offer is simply one with all default values. The others are default values except the ones that I set.
So, while it's a lot of work, if you want to clean up your initialization step, you need to use one of these options for each of your classes that have fields in them. Then use the initialization methods that I included with each method.
Good luck! Does any of this need further explanation?
I've always preferred using builder-pattern-with-a-twist because it provides much more than the basic approach of the builder pattern.
But what happens when you want to tell the user that she must call one builder method or the other, since it is crucial for the class you’re trying to build.
Think about a builder for a URL component. How would one think about the builder methods for encapsulating access to URL attributes, are they equally important, do they interact with each other, etc? While the query parameters or fragment are optional the hostname is not; you could say that protocol is also required but for that you can have a meaningful default, like http right?
Anyway, I don't know if this makes sense to your particular problem but I thought it would be worth mentioning for others to have a look at it.
Some nice answeres are already given here!
What came to my mind as an addition is Domain Driven Design. Specific the Building blocks part, with Entity, Value Object, Aggregate, Factory etc.
A nice introduction is given in Domain Driven Design - Quickly (pdf).
I just provide this answer because it was mentioned in a comment and I think it should also be a part of this enumeration of Design Patterns.
Null Object Design Pattern
Intent
The intent of a Null Object is to encapsulate the absence of an object by providing a substitutable alternative that offers suitable default do nothing behavior. In short, a design where "nothing will come of nothing"
Use the Null Object pattern when
an object requires a collaborator. The Null Object pattern does not introduce this collaboration--it makes use of a collaboration that already exists
some collaborator instances should do nothing
you want to abstract the handling of null away from the client
Here you find the full part of "Null Object" Design Pattern
Ideally, an object should not be concerned about instantiating its dependencies. It should only worry about things that it is supposed to do with them.
Have you considered any dependency injection framework? Spring or Google's Juice are quite versatile and have a small footprint.
The idea is simple, you declare the dependencies and let the framework decide when/how/where to create them and 'inject' it into your classes.
If you don't want to use any framework, you can take design notes from them and try to emulate their design patterns and tweak it for your use-case.
Also, you can simplify things to a certain extent by making proper use of Collections. For example, what additional feature does Offers have other than storing a collection of Offer? I'm not sure what your constraints there are but, if you can make that part a bit more cleaner you would have massive gains in all places where you are instantiating the objects.
Dozer framework provides nice way to do copy values from ws object to your dto. Here is another example. Additionally if the getter/setter names are the same of both class you dont need custom converter
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.
i need to fill an Array with different data types
InvoiceItem[] invoiceItems;
int test = 3;
int i = 0;
This needs to be in the Array:
InvoiceItem invoiceItem = new InvoiceItem();
invoiceItem.setItemType("TestItem");
invoiceItem.setArticleNo("TestItemID");
invoiceItem.setDescription("TestDescription");
invoiceItem.setQty(1);
invoiceItem.setPrice(new BigDecimal(20.00));
invoiceItem.setVat(new BigDecimal(5.0));
There is the possibility that there is more than one InvoiceItem (test=3), so it needs to be in a loop.
It has to be an Array, i need to pass it to another class which only accepts an Arrays.
How can i achieve this?
Edit: I will try to make my question more clear:
I need to know how to put these
invoiceItem.setItemType("TestItem");
invoiceItem.setArticleNo("TestItemID");
invoiceItem.setDescription("TestDescription");
invoiceItem.setQty(1);
invoiceItem.setPrice(new BigDecimal(20.00));
invoiceItem.setVat(new BigDecimal(5.0));
in an Array:
int countofInvoiceItem = 3; // there are 3 InvoiceItem
InvoiceItem[] invoiceItems = new InvoiceItem[countofInvoiceItem];
Where there can be more than one InvoiceItem.
Method looks like this:
public final ResponseCreateInvoice CreateInvoice
(Invoice Invoice, InvoiceItem[] InvoiceItems, Address DeliveryAddress, Address InvoiceAddress, String UserID, String Password)
(This is given and i can not change)
and returns
ResponseCreateInvoice inv = wsClient.createInvoice(invoice, invoiceItems, deliveryAddress, invoiceAddress, userID, password);
i am sort of new to Java (or arrays), so this may be an easy question, but i don't really get it. Also does it matter that there are Strings and Int, BigDecimal etc mixed together in an Array?
You just need to declare your array as an array of type T where T is a superclass of all the classes of the objects you want to fill it with. In the worst case, it would be Object but it's bad design 9 times out of 10.
I would recommend you to make a class that holds everything you need as follows:
public class YourClass{
int id;
double value;
String description;
//and so on
//create getters and setters
}
And you can use this class to pass array of objects to another class.
Put your objects of the class in the Array
For example
YourClass[] objects = new YourClass[SIZE];//define number of objects you need
And you can pass each and every objects separately or as a whole to another class.
And in your receiving class, you can have a constructor as:
public YourRecievingClass(YourClass[] object){
//and recieve here as you need; ask further if you need help here too
}
I think this is the best way to adopt though your question is not 100% clear
Based on your edit, your original question is off base. You do not want to create an array of different types but instead only want to create an array of one type and one type only, that being an array of InvoiceItems. You are confusing object properties with array items, and they are not one and the same. This code here:
invoiceItem.setItemType("TestItem");
invoiceItem.setArticleNo("TestItemID");
invoiceItem.setDescription("TestDescription");
invoiceItem.setQty(1);
invoiceItem.setPrice(new BigDecimal(20.00));
invoiceItem.setVat(new BigDecimal(5.0));
is where you are changing the properties of a single InvoiceItem.
It seems that your InvoiceItem class has String fields for item type, for article number, for description, an int field for quantity, a BigDecimal field for price and a BigDecimal field for VAT. And so your array would look simply like:
InvoiceItem[] invoiceItems = new InvoiceItem[ITEM_COUNT]; // where ITEM_COUNT is 3
You could use a for loop to then create your items:
for (int i = 0; i < invoiceItems.length; i++) {
invoiceItems[i] = new InvoiceItem();
}
And you could perhaps use the same for loop to fill in the properties of each InvoiceItem in the array:
for (int i = 0; i < invoiceItems.length; i++) {
invoiceItems[i] = new InvoiceItem();
invoiceItems[i].setItemType(???);
invoiceItems[i].setArticleNo(???);
invoiceItems[i].setDescription(???);
invoiceItems[i].setQty(???);
invoiceItems[i].setPrice(???);
invoiceItems[i].setVat(???);
}
But the unanswered question is, ... where do you get the data for each property of each InvoiceItem in the array? Is this information contained in a file? Is it inputted by the user? That is something you still need to tell us.
With which types of data? In general, you could use:
Object[] myArray;
All classes are subclasses of Object.
I've a class -
public class Data implements Identifiable{
private Integer id;
public Integer getId(){
return id;
}
}
now I've two collections-
List<Data> data1 = // few hundred Objects
Set<Integer> dataIds = // few object ids
I would like to extract the List<Data> from data1 which has ids in dataIds
How should be my approach? I'va guava in my classpath so can go with guava's Functional approach if comparable in performance/efficiency .
Unless all you want to do is iterate through the result once or you need a reusable live filtered view, you probably want a non-view list containing the matches. Creating a List or Set to store the result and then iterating through the data list and adding matches is a perfectly good approach and easy to understand!
List<Data> result = Lists.newArrayList();
for (Data data : data1) {
if (dataIds.contains(data.getId()))
result.add(data);
}
I see your Data class implements an Identifiable interface. Given that, you could create a Function<Identifiable, Integer> that gets the ID... Identifiables.getIdFunction() or something. This is nice because it'd likely be useful in various other places (I talk about that approach in a blog post here). With that in place, doing this with Guava would be fairly simple as well:
Predicate<Identifiable> predicate = Predicates.compose(
Predicates.in(dataIds), Identifiables.getIdFunction());
List<Data> filtered = Lists.newArrayList(Iterables.filter(data1, predicate));
This is basically functionally equivalent to the first example, but seems like it'd be harder to understand. Since there isn't any clear benefit to doing this (unlike in a situation where you want to just use the live view), my recommendation would be to just go with the first.
How about
Collections2.filter(
data1,
new Predicate<Data>() {
public boolean apply(Data d) {
return dataIds.contains(d.getId());
}
}
)
p.s. remember not to overcomplicate things, unless truly necessary.
With LambdaJ you could write:
List<Data> result = extract(data1, on(Data.class).getId());
I'm looking for a way to store different data types in one fixed length collection so I can set/get elements by index. What's the best way to go about this?
Thanks!
EDIT:
Should this work?
private List t=new ArrayList();
t.set(2,"test");
I get this: java.lang.IndexOutOfBoundsException: Index: 2, Size: 0
Should this work?
private List t=new ArrayList();
t.set(2,"test");
No it shouldn't. A List doesn't automagically grow if you call set with a position that is beyond the end of the list. (See the javadoc.)
If you want to do that kind of thing you have to fill the List with null elements first; e.g.
private List t=new ArrayList();
for (int i = 0; i < LIMIT; i++) {
t.add(null);
}
...
t.set(2,"test");
But I'd also like to reiterate the point that various other answers have made. You should write a class and do this in a type-safe fashion. Stuffing things into an Object[] or List<Object> ... and hoping that you get the indexes and types right ... gives you fragile code. It is bad practice.
You need a Javabean. Create a class which represents the whole picture of all those different properties together. E.g. an User with id, name, gender, dateOfBirth, active, etc.
public class User {
private Long id;
private String name;
private Gender gender;
private Date dateOfBirth;
private Boolean active;
// Add/generate c'tor(s)/getters/setters/equals and other boilerplate.
}
This way you end up with a clear and reuseable abstraction.
User user = new User();
user.setName("John Doe");
user.setGender(Gender.MALE);
// ...
See also:
What is a Javabean?
You can do such a thing with List. It has get/set methods by index. I don't see why fixed length is important here.
You can always encapsulate precisely the behavior you want in a class of your own devising. You can have a backing array to manage it for you, but you'll have to do all the work yourself.
Can't you make an array of Objects? Which means everything except the primitive types (int, char, boolean, etc.); if you want to store them you have to wrap them in their corresponding Object Wrapper classes (Integer, Character, Boolean, etc.) So like:
mult_type[0] = "A String";
mult_type[1] = new Integer(42);
mult_type[2] = new Long(7149994000);
and so on. Although mult_type[i] is an Object by definition, the entry
stored there can be any subclass of Object. When you want to retrieve them,
you can examine them to find out what class they actually belong to. There
are a couple of ways to do this, one is to use the "instanceof" operator
like so:
if (mult_type[i] instanceof Integer) {
Integer anInteger = (Integer)mult_type[i];
int anInt = anInteger.intValue();
}
Notice that you have to "cast" the object to its actual class as you
retrieve it.