Java: The most efficient way to write pojo with ArrayList - java

What is the most correct and/or efficient way in terms of time & memory consumption to write simple pojo class containing ArrayList? (Regarding java mechanism for references, pass by ref', assignments etc.):
public class MyClass {
//1. Do we need to initialize here?
public List<String> mList = new ArrayList<>();
//2. Do we need to declare D. Constructor?
public MyClass() {}
//3. Need to initialize the list here or just pass?
public MyClass(List<String> list) {
this.mList = list;
}
//4. Better way for copy/assignment?
public void setMlist(List<String> list) {
this.mList = list;
}
public List<String> getMList() {
return this.mList;
}
}

Do we need to initialize here?
No, initialize it only when you need it. Make sure to check for null if there is possibility of using it without being initialized.
Do we need to declare D. Constructor?
If you do nothing in it, I don't really see the point of having it. Note that some people prefer to still declare it writing a comment in it and indicate that it should do nothing :
public MyClass(){
//NOP
}
See NOP. This won't change anything related to memory usage. However logically, the default constructor should initialize the list instead of initializing it at the beginning. So we have two options, we pass one that already exists (with the parameterized constructor) or we use the default constructor and create an empty list.
Need to initialize the list here or just pass?
Just pass, else what would be the point of receiving it as an argument ? If you initialize it and re-assign that would make no sense. You may want to check if the received one is null and initialize it otherwise.
Better way for copy/assignment?
If really you want to make a copy, you might want to check Collections#copy. However, this is not the point of setter, what you have done here is correct.

This is impossible to answer without knowing about your intentions. There's a surprisingly large number of design decisions you have to make, even when writing a "simple pojo class containing ArrayList". Here are 8 off the top of my head, but there are many, many more.
Do you want to make the field public or private? (probably private.)
If private, do you want to provide a get method?
Do you want to provide a set method, or do you want the field to be initialized once and for all in the constructor?
Should the argument to your constructor and/or set method only accept a List<String> or will you allow something more general, such as Collection<? extends CharSequence>?
Do you want people using your class to be able to modify mList? (This is different from reassigning mList.)
Do you want to write subclasses, or do you want the class to be final?
If you want to write subclasses, do you want to make any of the methods final?
Do you want to provide a constructor with no argument that initialises the ArrayList to a sensible default value?
The most subtle one of these questions is the 5th. Suppose somebody does this
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
myClass.setMList(list);
and then later does this
System.out.println(myClass.getMList());
They may expect to see [a, b, c], but this may not happen because it is possible to modify the internals of myClass in between. For example:
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
myClass.setMList(list);
list.remove(1); // Modifies the List stored by myClass
System.out.println(myClass.getMList()); // prints [a, c]
If you don't want this kind of thing to be possible you'll have to write a class that copies List objects in the constructor, setter and getter. This will have consequences for performance (but will be tiny for small lists).
There are no right or wrong answers. You need to think through who is using the class, why they need it, and weigh up all the relevant factors when answering all of the above questions.

Related

No arg constructor or arg constructor

In my program I read a fixed length file, stored each string in a local variable, and then stored every value into a class type array list. For creating the object of an array list, I used argument constructor with all the variables. The below code demonstrates this.
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel(a,b);
ArrayList<SampleModel> sampleList = new ArrayList<>();
sampleList.add(sm);
I find this absolutely right but my colleague asked me to change it to a no arg constructor and call getters and setters instead. That would be like below.
SampleModel sm = new SampleModel();
ArrayList<SampleModel> sampleList = new ArrayList<>();
String a = "text1";
String b = "text2";
sm.setA(a);
sm.setB(b);
sampleList.add(sm);
Is there any reason to prefer a no arg constructor over argument constructor? (My program has around 15 variables)
It depends on how the class will be used.
For example, an immutable class will need a constructor that takes arguments, and no setters.
But a Java Bean will need a no-argument constructor, and setters.
Some things to consider:
Encapsulation can be valuable. Other than special cases like JavaBeans, usually the interface of the class can be designed based on the desired interactions, not on the current set of data members.
Methods have names. Java does not support named arguments. Method names communicate how an actual parameter is being used, in the calling code. If your class has more than a handful of parameters, passing them via methods can result in more readable calling code.
Immutable classes have value. If you're adding named setters directly in your class, it won't be immutable. The builder pattern allows you to accept construction parameters even for immutable classes.
Whether I use accessors and mutators for a class variable depends on two things:
Whether the variable is essential or optional to the object.
Whether it might ever change in the course of using the object, or whether it is final.
Variables that are necessary and final should be in the constructor, in my opinion, and should not have mutators. Variables that are optional should have accessors and mutators. Variables that are essential but might change are up to your discretion. I would probably put them in the constructor, but use a Builder design pattern to avoid having a long list of arguments for the constructor.
A constructor that takes arguments is essentially for convenience (although that's not always the case if the object requires arguments in order to be constructed properly, it is here without seeing anymore context); it's doing the exact same thing as the set methods are doing.
There is no reason to not have a constructor take arguments, as long as those arguments "make sense" in the context of the object. In other words, it's more of a semantics thing to consider than a correctness thing.
If the constructor is:
public SampleModel(String a, String b)
{
this.a = a;
this.b = b;
}
It probably doesn't make a difference.
It might just be that it's easier to see whats going on than having a large comma separated list. This might also be a nice place to use Double Brace Initialization:
String a = "text1";
String b = "text2";
SampleModel sm = new SampleModel() {{
setA(a);
setB(b);
}};
ArrayList<SampleModel> sampleList = new ArrayList<>() {{
add(sm);
}};
Quotation from Fowler and Beck book: "Refactoring"
Long Parameter List
In our early programming days we were taught to pass in as parameters everything needed by a routine. This was understandable because the alternative was global data, and global data is evil and usually painful. Objects change this situation because if you don't have something you need, you can always ask another object to get it for you. Thus with objects you don't pass in everything the method needs; instead you pass enough so that the method can get to everything it needs. A lot of what a method needs is available on the method's host class. In object-oriented programs parameter lists tend to be much smaller than in traditional programs. This is good because long parameter lists are hard to understand, because they become inconsistent and difficult to use, and because you are forever changing them as you need more data. Most changes are removed by passing objects because you are much more likely to need to make only a couple of requests to get at a new piece of data. Use Replace Parameter with Method when you can get the data in one parameter by making a request of an object you already know about. This object might be a field or it might be another parameter. Use Preserve Whole Object to take a bunch of data gleaned from an object and replace it with the object itself. If you have several data items with no logical object, use Introduce Parameter Object. There is one important exception to making these changes. This is when you explicitly do not want to create a dependency from the called object to the larger object. In those cases unpacking data and sending it along as parameters is reasonable, but pay attention to the pain involved. If the parameter list is too long or changes too often, you need to rethink your dependency structure.

Object list within an object

I have created an object that contains an Arraylist and that Arraylist contains objects. My question is, how do i point to the objects in the Arraylist?
the original Object contains:
some attributes,
list = new arraylist
The List contains:
14 objects of similar data
This seems like a fairly simple task, but because you did not give me your exact code, I am just going to assume.
Let's say this is the class of the object that you were talking about
public class ClassA {
public ArrayList<Integer> list = new ArrayList<>(); //I guess integers are "similar data"
}
Now you have that object, called obj
ClassA obj = new ClassA ();
You can just access the array list by doing this
obj.list
For example you can add an item to the array list like this:
obj.list.add(10);
And you can retrieve the first item
obj.list.get(0);
Easy!
If you think you understand little of the above, I'll explain. If you think you understand it completely, you can just accept the answer and go.
Almost every class declare members. And so does your class, ClassA. Any accessible member can be accessed using .. We call it the dot operator.
And what is an accessible member?
Different access modifiers provide different accessibility, read this to find out more: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html In the above example, list is a member, and it is declared public This means that it is accessible everywhere.
This is why you can access it using ..
Actually, I think you must have used this technique before! When you call
System.out.println ("Hello World");
You use the dot to access members!
In the System class, there is a member called out. out is of type PrintStream. In PrintStream class, there is another member called println! See? that's how Java works.
If you still don't understand, read this part again. If you understand, please click that green tick to accept the answer.

What's the harm in using Anonymous class?

The question arose while reading a answer to this question - How do I join two lists in java. This answer gave the solution
List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } };
Reading the comments, users said it was evil and ugly and should not be used in production.
I would like to know what's the harm in using this? Why is it ugly, evil or bad to use in production?
Except for the already mentioned issues regarding good programming style and inheritance misuse, there is one more subtle problem - inner classes and (non-static) anonymous class instances act as closures. This means that they keep an implicit reference to the enclosing class instance. This can result in preventing of garbage collection and in the end, a memory leak.
Given an example piece of source code:
public interface Inner {
void innerAction();
}
public class Outer {
public void methodInOuter() {}
private Inner inner = new Inner() {
public void innerAction() {
// calling a method outside of scope of this anonymous class
methodInOuter();
}
}
}
What happens at compilation time, is that the compiler creates a class file for the new anonymous subclass of Inner which gets a so-called synthetic field with the reference to the instance of the Outer class. The generated bytecode will be roughly equivalent to something like this:
public class Outer$1 implements Inner {
private final Outer outer; // synthetic reference to enclosing instance
public Outer$1(Outer outer) {
this.outer = outer;
}
public void innerAction() {
// the method outside of scope is called through the reference to Outer
outer.methodInOuter();
}
}
Such capture of reference to the enclosing instance happens even for anonymous classes that never actually access any of methods or fields of the enclosing class, such as the double-brace initialized (DBI) list in your question.
This results in the fact that the DBI list keeps a reference to the enclosing instance as long as it exists, preventing the enclosing instance from being garbage collected. Suppose the DBI list happens to live for a long time in the application, for example as a part of the model in MVC pattern, and the captured enclosing class is for example a JFrame, which is quite a large class with lots of fields. If you created a couple of DBI lists, you would get a memory leak very quickly.
One possible solution would be using DBI only in static methods, because there is no such enclosing instance available in their scope.
On the other hand, I would still argue that using DBI is still not necessary in most cases. As for the list joining, I would create a simple reusable method, which is not only safer, but also more concise and clear.
public static <T> List<T> join(List<? extends T> first, List<? extends T> second) {
List<T> joined = new ArrayList<>();
joined.addAll(first);
joined.addAll(second);
return joined;
}
And then the client code becomes simply:
List<String> newList = join(listOne, listTwo);
Further reading:
https://stackoverflow.com/a/924536/1064809
The "ugly" and "do not use in production" comments refer to this specific use of anonymous classes, not to anonymous classes in general.
This specific use assigns newList an anonymous subclass of ArrayList<String>, an entirely new class created with a single purpose in mind - namely, initializing a list with the content of two specific lists. This is not very readable (even an experienced reader would spend a few seconds figuring it out), but more importantly, it can be achieved without subclassing in the same number of operations.
Essentially, the solution pays for a small convenience with creating a new subclass, which may result in problems down the road, for example, in situations when you try to persist this collection using an automated framework that expects collections to have specific types.
This particular use of anonymous classes has several problems:
it's a little-known idiom. Developers that don't know it (or know it an don't use it a lot) will be slowed down when reading and/or modifying code that uses it.
it's actually misusing a language feature: you're not trying to define a new kind of ArrayList, you just want some array list with some existing values in it
it creates a new class that takes up resources: disk space to hold the class definition, time to parse/verify/... it, permgen to hold the class definition, ...
even if the "real code" is slightly longer, it can easily be moved into an aptly-named utility method (joinLists(listOne, listTwo))
In my opinion #1 is the most important reason to avoid it, closely followed by #2. #3 is usually not that much of a problem, but should not be forgotten.
Because you don't need a separate subclass - you just need to create a new ArrayList of the normal class, and addAll() both lists into it.
Like so:
public static List<String> addLists (List<String> a, List<String> b) {
List<String> results = new ArrayList<String>();
results.addAll( a);
results.addAll( b);
return results;
}
It's evil to create a subclass, that isn't needed. You don't need to extend or subclass behaviour - just change data values.
It's not a bad approach per se, say, in performance or anything like that, but the approach is a bit obscure and when using something like this, you always (say, 99%) have to explain this approach. I think that's one of the biggest reasons not to use this approach, and while typing:
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
is a little more typing, it's a bit easier to read, which helps a lot in understanding or debugging code.
In your example it really looks evil and ugly, at least to me - it's difficult to understand what's going on in the code. But there are some patterns of using anonymous classes that people are used to because they see them very often, eg
Arrays.sort(args, new Comparator<String>() {
public int compare(String o1, String o2) {
return ...
}});
I would call the above a best practice case.

Returning const reference of an arraylist

I really admire java features and I don't want to give up using it for the next problem:
I have a class that might be inherited, and inside of it is a private ArrayList arr; So the setter function is ok , but the getter function return arr; returns the reference to that variable which anyone capable of editing that whole array which I don't want and private wouldn't make any sense !
In C++ I would just return const arr; and it would return constant reference to the variable.
I so much need the variable not to be cloned or manually copied because there are so many calculations that require to (READ ONLY the variable) WHY there is no const returning in java ???? is there any way I could escape copying ?
p.s (final ArrayList<Integer> arr;) isn't an option cause that array always changes size or element values.
If I couldn't find a fix to that I'm threatening to go back to C++ or make everything public and you should never get my software :D
EDIT: one more important question: Am I asking for something that's not good (Software engineering wise) I mean if JAVA creators thought of not having const reference (returning Read only references) then I must be asking for something that can be handled in other way. or my program design is wrong I'm so confused.
Wrap the return value with java.util.Collections.unmodifiableList. It does not make a copy of the data, but wraps the original list, and delegates read-only operations to the underlying list. Operations which would modify the list are rejected at runtime via UnsupportedOperationException.
Your
return arrayList;
becomes
return Collections.unmodifiableList(arrayList);
Unfortunately the read-only constraints won't be enforced by the compiler. They will, however, be enforced at runtime.
You also have available to you: unmodifiableSet, unmodifiableMap, unmodifiableCollection, unmodifiableSortedSet, and unmodifiableSortedMap. And if these are not enough, you can still take inspiration from this general design approach, and create your own custom read-only wrapper classes.
:) You have several options:
Don't expose getter, provide only methods which are allowed to call, e.g.
public void addToList(Object arg) { this.arr.add(arg);}
Return immutable object:
public List getArr() { return Collections.unmodifiableList(this.arr); }
You could also use Google Guava's immutable collections. In this case, you would store an ImmutableList in your field.
Of course, if your class needs to modify this list internally, using ImmutableList might turn out to be a bad idea, since you'll need to create a new ImmutableList instance and reassign it to the field each time...
But it's perfect when you know the List won't change after object construction.
Immutable example (list won't change after object construction)
#Immutable
public final class Foo {
#Nonnull
private final ImmutableList<String> list;
public Foo(#Nonnull List<String> list) {
// you could also compute the appropriate list here
// before assigning it to the field
this.list = ImmutableList.copyOf(list);
}
public ImmutableList<String> getList() {
return list;
}
}
Mutable example (list may only be modified using the setter)
public class Foo {
#Nonnull
private ImmutableList<String> list = ImmutableList.of();
public ImmutableList<String> getList() {
return list;
}
public void setList(#Nonnull List<String> list) {
this.list = ImmutableList.copyOf(list);
}
}
Remarks
I know it's often advised to make methods return the most generic type possible (List in this case), but I prefer to declare my getter's return type as an ImmutableList, because it acts as documentation (no need to document the returned list's immutability in the Javadoc) and as an API contract. It's like saying "I guarantee this list to be immutable, you do not have to worry or defensively copy it". And it is very concise.
ImmutableList.copyOf() is great, since it automatically rejects null lists (by throwing NullPointerException). It also rejects null elements. And it won't copy the source list if it's already an ImmutableList, which avoids useless object instantiation.
In the second example, I initialize the field to an empty ImmutableList using ImmutableList.of(), because it's a good practice to return empty collections instead of null values (Null Object pattern). You might think that this creates needless object instantiation, but ImmutableList.of() actually returns a singleton.
unmodifiableList is definitely the answer.

java general question about interfaces

considering i have a method which gets a List passed as an param. Within this method i want to use for instance an ArrayList specific function on that list (lets say trimToSize()). What would be the general approach to deal with a problem like this ?
Here two example:
First approach (i don't think this is good)
private void doSomething(final List<T> list) {
// ... do something
((ArrayList<T>) list).trimToSize();
// ... do something
}
Second approach (i think this one is better)
private void doSomething2(final List<T> list) {
final List<T> myList = new ArrayList<T>();
// Collections.copy(myList, list); or
myList.addAll(list);
((ArrayList<T>) myList).trimToSize();
//..do something
}
I'm curious whats the best solution for a problem like this.
Well, the preferred option is to just write the method to take an ArrayList in the first place. If you need ArrayList specific functionality, the method has no business taking a List. Transfer the responsibility of ensuring that the parameter is of the right type to the caller and don't fiddle around with it inside the method.
Why not just declare method as a private void doSomething(final ArrayList<T> list), if you want only ArrayList as parameter?
If you're accepting any object implementing the List interface then your function should only invoke methods implemented from the interface.
If you want to invoke functions from ArrayList class then have ArrayList as your parameter. Much safer than either of your options.
The second we have huge overhead with big lists, but is safer. I would go for the first, but with check whether the provided List is ArrayList and then make a cast.
You should have a strong reasons to not take an ArrayList as a parameter though.
The first option you've shown only works for ArrayLists so it's not an option if you want to support any type of List. If you want to support any type of List you must convert (not cast) it to an ArrayList.
I think there might be some confusion because the List and ArrayList are so closely related (by inheritance). It is only coincidence that the parameter type and the class we need to call the function on are related in this way.
If we abstract the requirements a bit:
We need to act on a series of values
We need to use trimToSize() on the
series of values.
If the values were coming as an array there would be no question but to create a new ArrayList with the values from the array and then use trimToSize(), because casting would not be an option. It is just bad luck that the method we need trimToSize() happens to be on a subclass of List, and the author wants to pass the values as a List.
What about
private void doSomething(final List<T> list) {
final ArrayList<T> arrayList;
if (list instanceof ArrayList) {
arrayList = (ArrayList<T>) list;
} else {
arrayList = new ArrayList<T>(list);
}
...
arrayList.trimToSize();
}
Of course, I agree with Chinmay Kanchi: for a private method, it makes no sense to accept a more general type than necessary. My approach is only feasible if it causes no problems to modify the given list.
Your first method changes the List passed to the method while the other one doesn't. Two methods are not comparable.
Since it is a private method, the convention of using the List interface is not overly important. There is no public API affected so use whichever method is the most convenient for its usage in the class.
For example, if 5 other methods call this method with potentially varying types of List, then use your second option and centralize the conversion in 1 method (you can even throw in a check for type and not convert if you like). If your class only deals with ArrayList internally anyway, and you know that is what it will be when called, then declare it as a ArrayList and make your life easy for yourself.

Categories