Concatenate lists with double brace initialization - java

I would like to concatenate two array lists as it shows in the answer:
final List<String> l1 = Lists.newArrayList(...);
final List<String> l2 = Lists.newArrayList(...);
List<String> l = new ArrayList<String>() { { addAll(l1); addAll(l2); } };
Is there any non style reason I should not use it this way?

If you are already using Guava, you can do this using the following one-liner:
List<String> l = FluentIterable.from(l1).append(l2).copyInto(new ArrayList<String>());
I personally don't like double braces. This produces new class just for the purpose to initialize it in different way. New class means bigger target jar file, more memory is necessary for JVM to store classes, bigger inheritance table for JIT compiler, etc. This can become significant if you use such approach everywhere. If you return this ArrayList to another component and your current component is not used anymore (for example, you are using OSGi or other module system), you may end up having hanging ClassLoader which is linked only by this anonymous class. Also if you care about serialization, you should declare serialVersionID in this new class. Even if you don't care, you may have a warning about this.

Well, first of all, it depends on what you wish to do with duplicate elements. This code will keep any duplicates (i.e. if l1 and l2 both contain "someString", l will contain two "someString"), so it's not really a union operation. Calling it a concatenation of two lists would be more accurate.
Other than that, using the "double brace" is actually creating an instance of an anonymous class that extends ArrayList. I think it's a bad code style.
List<String> l = new ArrayList<String>(l1);
l.addAll(l2);
is clearer and is not longer to write.

Related

What is the difference in time & space complexity between declaring an ArrayList object and a List object?

I know that an instance of ArrayList can be declared in the two following ways:
ArrayList<String> list = new ArrayList<String>();
and
List<String> list = new ArrayList<String();
I know that using the latter declaration provides the flexibility of changing the implementation from one List subclass to another (eg, from ArrayList to LinkedList).
But, what is the difference in the time and space complexity in the two? Someone told me the former declaration will ultimately make the heap memory run out. Why does this happen?
Edit: While performing basic operations like add, remove and contains does the performance differ in the two implementations?
The space complexity of your data structure and the time complexity of different operations on it are all implementation specific. For both of the options you listed above, you're using the same data structure implementation i.e. ArrayList<String>. What type you declare them as on the left side of the equal sign doesn't affect complexity. As you said, being more general with type on the left of the equal sign just allows for swapping out of implementations.
What determines the behaviour of an object is its actual class/implementation. In your example, the list is still an ArrayList, so the behaviour won't change.
Using a List<> declaration instead of an ArrayList<> means that you will only use the methods made visible by the List interface and that if later you need another type of list, it will be easy to change it (you just change the call to new). This is why we often prefer it.
Example: you first use an ArrayList but then find out that you often need to delete elements in the middle of the list. You would thus consider switching to a LinkedList. If you used the List interface everywhere (in getter/setter, etc.), then the only change in your code will be:
List<String> list = new LinkedList<>();
but if you used ArrayList, then you will need to refactor your getter/setter signatures, the potential public methods, etc.

What class to use for ArrayList?

I just wanted to clarify this question I had for a while for more efficient and 'correct' code.
I gave a class 'Student' with objects in an array list of objects. I have another class called Class which has an array list of references to the very same objects in the Student class.
Should I declare the 'Class' class as
ArrayList<Student> myStudents = new ArrayList<Student>();
or
ArrayList<Class> myStudents = new ArrayList<Class>();
Also another part of the question is I have seen people declare arrayLists as ArrayList<Student> myStudents = new ArrayList<>();
where the second half of the carrots are left empty. What exactly does the difference mean? Does this mean that the array list is not an object of any class?
Thank you so much for your time and help
Cheers
It depends on what you want to store in the list rather than where you are using it. If you're storing Student objects, then you'll use ArrayList<Student>().
The type omitted on the right side is called type inference (added in java 7), which means the type parameter on the right side will be inferred from the type of the assignment variable on the left. It helps to write the code in a cleaner way. For e.g.
Writing below is easier:
List<Some<Type<Another>>> var = new ArrayList<>();
than:
List<Some<Type<Another>>> var = new ArrayList<Some<Type<Another>>>();
Technically, neither.
You would want to do:
List<Student> myStudents = new ArrayList<>();
if you want to create an ArrayList with Student objects and
List<Class> myClasses = new ArrayList<>();
if you want to create an ArrayList with Class objects.
1) Note the variable names.
2) Note that you should always try to code to an interface (the left side is a List, not an ArrayList). This allows much greater flexibility since you're not dependent on the specific implementation of an ArrayList later on. This point is so powerful! You can write method signatures to accept objects of type List and then use an ArrayList, LinkedList or Stack or any class that implements a List. Depending on how you are using your ArrayList later, the Collection interface may be sufficient instead.
The diamond operator allows the compiler to infer the value of the type argument without having to type it all out. It's needed for backward compatibility for older Java versions.
As a general practice for performance optimization, you will also want to supply an initial capacity of an ArrayList if it's possible. So if you know that there are only 5 classes, then you would do:
List<Class> myClasses = new ArrayList<>(5);

Initialization and naming, ArrayList in Java

I have several objects I want to store in an arrayList that represents a single assembly language instruction (eg Add, Jump, etc). The objects in each ArrayList are constant for a given instruction, so I just need to load each of the objects for a given instruction into the proper arrayList once at load time.
The tedious part is that I need to name each of the objects before they're added to the arrayList:
static {
...
ArrayList<CodeFrag[]> intIntGtrEqlProtoCode = new ArrayList<CodeFrag[]>();
...
intIntGtrEqlProtoCode.add(intIntGtrEqlInst1);
CodeFrag[] intIntGtrEqlInst2 = {Subtract};
intIntGtrEqlProtoCode.add(intIntGtrEqlInst2);
CodeFrag[] intIntGtrEqlInst3 = {Duplicate};
...
}
I have a feeling like there is a way to avoid doing all this extremely tedious naming. Can someone point it out to me?
You could do something like this:
CodeFrag[] arr = {Subtract, Duplicate, Foo, Bar};
for (CodeFrag c : arr)
intIntGtrEqlProtoCode.add(new CodeFrag[]{c});
Also, if all of the arrays have length 1, couldn't you replace it with a List<CodeFrag>? Then you could just do
intIntGtrEqlProtoCode = new ArrayList<CodeFrag>(Arrays.asList(Subtract, Duplicate, Foo, Bar));

Typed vs. Non-typed ArrayList

What's the difference between using a typed vs. non-typedArrayList in Java?
For example, Using an ArrayList of CustomObject:
Typed:
ArrayList<CustomObject> typedArray = new ArrayList<>();
typedArray.add(new CustomObject);
or non-typed:
ArrayList<> nonTypedArray = new ArrayList<>();
nonTypedArray.add(new CustomObject);
Is there any situation where the latter is preferred? Is there any difference when the ArrayList is holding different datatypes, e.g. an ArrayList of String, Int, etc.?
In the Second Approach, it is not mandatory to add only CustomObject whereas it is in 1st Approach, otherwise, you will get Compilation Error.
ArrayList<CustomObject> typedArray = new ArrayList<>();
typedArray.add(new CustomObject());
This approach is generally preferable as there are no chances of having Class Cast Exception but in second approach there are high chances of that !!
JavaDocs explains it beautifully : Why to prefer Generics
Stronger type checks at compile time.
Elimination of casts.
Enabling programmers to implement generic algorithms.
It's never preferable to use the latter option. I don't think that is even possible. I think you meant:
ArrayList nonTypedArray = new ArrayList();
This syntax is left over from Java 1.4 and earlier. It still compiles for the purposes of backwards compatibility.
Generics was introduced in Java 1.5 which allowed you to specify the types between angled brackets.
It is always preferable to use generics because it is more type-safe.
That is, if you specify
ArrayList<String> typedArray = new ArrayList<String>();
Then you cannot accidentally add an integer to this array list; if you tried to add an integer, the program would not compile.
Of course, Generics ensures type safety at compile time. At runtime ArrayList<String> typedArray = new ArrayList<String>(); becomes ArrayList typedArray = new ArrayList();. This is to maintain backwards compatibility.
What's the difference between using a typed vs. non-typed ArrayList in
Java?
A typed/generic ArrayList is a collection of objects in which the "type" of the object is defined in angled brackets. Generics were introduced in Java 5 to create type-safe collections.
Before Generics the collection was called untyped/raw type collection because there was no way to specify the compiler the type of the collection being created.
The difference between both is to detect type-safe operations at compile time.
In both of your cases, you are adding object(s) of type 'CustomObject' to the ArrayList. There will be no issue while adding elements in the list, as both lists will consider them as typed objects.
Typed:
ArrayList<CustomObject> typedArray = new ArrayList<CustomObject>();
typedArray.add(new CustomObject);
Untyped:
ArrayList<> nonTypedArray = new ArrayList<>();
nonTypedArray.add(new CustomObject);
Is there any situation where the latter is preferred?
I don't think so. As generics are recommended to be used while creating a list to ensure type-safe operations.
Is there any difference when the ArrayList is holding different
datatypes, e.g. an ArrayList of String, Int, etc.?
Surely, there is a reasonable difference. For an untyped list, you will need to add type-cast while fetching elements from a list. As there is a possibility of the compiler throwing a ClassCastException at runtime due to different types of elements.
In runtime, there is absolutely no difference, however in compilation time, using type parameters can save you from a plethora of errors, so it is always preferable to use generics properly.
The only case where raw types are used reasonably is in legacy applications, but even in this case, you try to use typed parameters if you can.
The use of type simplifies your coding removing the need of casting and also stores your data efficiently
https://docs.oracle.com/javase/tutorial/java/generics/why.html
Yeah, I know this is an old post. But I wanted to share an instance where an untyped ArrayList is useful: when you're writing a function that supposed to act on arbitrary element types. For example, suppose you want to make a generic shuffle function that knows how to shuffle an array. Like so:
ArrayList<Die> diceRolls = getGetPossibleDiceRolls();
ArrayList<Card> cardDeck = getPossibleCards();
ArrayList<GirlToDate> blackbook = getBlackbook();
shuffle(diceRolls);
shuffle(cardDeck);
shuffle(blackbook);
.
.
void shuffle(ArrayList array) {
int size = array.size();
for (int i=0; i<size; ++i) {
int r = random.nextInt(size - i) + i;
// Swap
Object t = array.get(i);
array.set(i, array.get(r));
array.set(r, t);
}
}
Some might argue "yeah, but the proper way to do this is to create an interface or subclass of something like a Shuffleable type..." But really?
In Java 1.7 and upwards you should normally use the constructor like this:
ArrayList<MyObject> list = new ArrayList<>();
or else for a more general List object:
List<MyObject> list = new ArrayList<>();
Observe that you only specify the type <MyObject> once, not twice. This makes your code easier to maintain. The <> causes the constructor to return an ArrayList which is already typed to match the field/variable to which it is being assigned - so that no cast will be required in the calling code.
Do not use new ArrayList() as the constructor. This returns an untyped ArrayList which then has to be cast to a type to match the field/variable to which it is being assigned. This means unnecessary type checking and casting and so generally reduces performance.

Always avoid in-out parameters in Java?

There's no doubt that in-out parameters leads to confused code since they may increase unexpected/unpredictabled side-effects.
So, many good programmers say :
Avoid in-out parameters for changing mutable method parameters. Prefer to keep parameters unchanged.
For a perfectionist programmer who expects his code to be the most clean and understandable, does this "rule" must be applied in all case ?
For instance, suppose a basic method for adding elements to a simple list, there's two ways :
First way (with in-out parameter):
private void addElementsToExistingList(List<String> myList){
myList.add("Foo");
myList.add("Bar");
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
addElementsToExistingList(myList);
Second way without out parameter :
private List<String> addElementsToExistingList(List<String> originalList){
List<String> filledList = new ArrayList<String>(originalList); //add existing elements
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(addElementsToExistingList(myList));
Pros of second way :
Parameter are not modified => no risk of unexpected side-effects for a new code reader.
Cons of second way :
Very verbose and very less readable ...
Of course, you would tell me that for a code as simple as this one, first way is really more convenient.
But, if we don't consider the difficulty of any concept/code, I juge the second way more logical and obvious for any readers (beginners or not).
However, it violates the CQS principle that consider "command" methods having void return with potential (but allowed since it's the convention) side-effects and "query" methods having a return type and without side-effects.
So, what should a motivate programmer adopt ? Mix of two accorging to the code case ? Or keep the "law" expecting to always avoid in-out parameters...
(Of course, method for adding Element is named for expliciting the example, and would be a bad name choice in real code).
I think the law should be:
Use what is more straight-forward, but always, always document the behavior of your methods extensively.
Your second example is a very nice case where without documentation you would have a guaranteed bug: the name of the method is addElementsToExistingList, but the method does not add elements to the existing list - it creates a new one. A counter-intuitive and misleading name, to say the least...
There is a third way. Wrap List<String> into a class that knows how to add elements to itself:
class ElementList {
private List<String> = new ArrayList<String>();
public void addElements(Element... elements);
}
I like this approach because it keeps the List implementation private. You don't have to worry if someone passes an immutable list to your method or whether parameters are modified. The code is simpler. Long method names like addElementsToExistingList are code smells that an object is trying to do something another object should be doing.
You should always document when mutating an object that is a parameter because otherwise this can have unintended side effects for the caller. In the first case I agree with the others that have commented that the method name is sufficient documentation.
In your second example, the elements that are already present in myList seem to be added twice. In fact you could entirely remove the parameter of the addElementsToExistingList method and rewrite it as:
private List<String> getElements() {
List<String> filledList = new ArrayList<String>();
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(getElements());
Note that this code is not equivalent to your second example because the elements are only added once, but I think this is actually what you intended. This is the style that I usually prefer. This code is easier to understand and more flexible than the first example without adding extra code (it may degrade performance very slightly but this usually isn't a concern). The client of getElements() can now also do other things with the element list besides adding it to an existing collection.
It's fine to change/mutate parameters as long as it's documented. And of course with a method name of "addElementsToExistingList", what else should someone expect? However, as someone previously pointed out, your second implementation returns a copy and doesn't modify the original, so the method name is now misleading. Your first way is a perfectly acceptable way of doing things. The only other additional improvements is to possibly add a true/false value to the return indicating true if only all the elements were added to the list.
In the case of your example the name makes it clear - "addElementsToExistingList" to me seems pretty clearly to hint that you're going to .. er.. you know. But your concern would be justified with a less obvious name.
For example, in ruby this is commonly handled with naming conventions
"a".upcase => gives you the uppercase of the variable, leaves the original unchanged
"a".upcase! => alters the original variable

Categories