Java initialize arraylist with one element

Initialization of an ArrayList in one line

It would be simpler if you were to just declare it as a List — does it have to be an ArrayList?

List places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata"); 

Or if you have only one element:

List places = Collections.singletonList("Buenos Aires"); 

This would mean that places is immutable (trying to change it will cause an UnsupportedOperationException exception to be thrown).

To make a mutable list that is a concrete ArrayList you can create an ArrayList from the immutable list:

ArrayList places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata")); 

And import the correct package:

As per my answer, if you’re not using methods specific to ArrayList , it would be better design to change the declaration to List . Specify interfaces, not implementations.

@Christoffer Hammarström: if he changes the declaration to List and uses the List places = Arrays.asList(. ); he will not be able to use places.add(«blabla»)

Just to be clear, asList(. ) returns a fixed size List that blows up on mutating operations like remove and clear , things the List contract claims to support. Even if you left declaration as List , you sill need to use List l = new ArrayList(asList(. )) in order to get an object that doesn’t throw OperationNotSupported exceptions. Liskov Substitution Principle anyone?

Actually, probably the «best» way to initialize the ArrayList is the method you wrote, as it does not need to create a new List in any way:

ArrayList list = new ArrayList(); list.add("A"); list.add("B"); list.add("C"); 

The catch is that there is quite a bit of typing required to refer to that list instance.

There are alternatives, such as making an anonymous inner class with an instance initializer (also known as an «double brace initialization»):

ArrayList list = new ArrayList() >; 

However, I’m not too fond of that method because what you end up with is a subclass of ArrayList which has an instance initializer, and that class is created just to create one object — that just seems like a little bit overkill to me.

What would have been nice was if the Collection Literals proposal for Project Coin was accepted (it was slated to be introduced in Java 7, but it’s not likely to be part of Java 8 either.):

Unfortunately it won’t help you here, as it will initialize an immutable List rather than an ArrayList , and furthermore, it’s not available yet, if it ever will be.

See stackoverflow.com/questions/924285 for more information about the double-brace initialization, pros and cons.

@Delight The «diamond operator» was introduced in Java 7, which wasn’t released when I wrote this answer back in 2009 😉

Читайте также:  Php парсер html таблиц

The simple answer

Java 9 or later:

List strings = List.of("foo", "bar", "baz"); 

List.of(. ) will give you an immutable List , so it cannot be changed.
Which is what you want in most cases where you’re prepopulating it.

This does not allow null elements.

Java 8 or earlier:

List strings = Arrays.asList("foo", "bar", "baz"); 

Arrays.asList(. ) will give you a List * backed by an array, so it cannot change length.
But you can call List.set(. ) , so it’s still mutable.

This does allow null elements.

* Implementation detail: It’s a private nested class inside java.util.Arrays , named ArrayList ,
which is a different class from java.util.ArrayList , even though their simple names are the same.

Static import

You can make Java 8 Arrays.asList even shorter with a static import:

import static java.util.Arrays.asList; . List strings = asList("foo", "bar", "baz"); 

Any modern IDE * will suggest and do this for you.

I don’t recommend statically importing the List.of method as just of , because it’s confusing.

* For example, in IntelliJ IDEA you press Alt+Enter and select Static import method.

Using Stream s

Why does it have to be a List ?
With Java 8 or later you can use a Stream which is more flexible:

Stream strings = Stream.of("foo", "bar", "baz"); 

You can concatenate Stream s:

Stream strings = Stream.concat(Stream.of("foo", "bar"), Stream.of("baz", "qux")); 

Or you can go from a Stream to a List :

import static java.util.stream.Collectors.toList; . var strings = Stream.of("foo", "bar", "baz").toList(); // Java 16 List strings = Stream.of("foo", "bar", "baz").collect(toList()); // Java 8 

But preferably, just use the Stream without collecting it to a List .

If you specifically need a java.util.ArrayList *

If you want to both prepopulate an ArrayList and add to it afterwards, use

List strings = new ArrayList<>(List.of("foo", "bar")); 
List strings = new ArrayList<>(asList("foo", "bar")); 
import static java.util.stream.Collectors.toCollection; List strings = Stream.of("foo", "bar") .collect(toCollection(ArrayList::new)); 

Then you can add to it after construction:

But again, it’s better to just use the Stream directly instead of collecting it to a List .

*You probably don’t need specifically an ArrayList . To quote JEP 269:

There is a small set of use cases for initializing a mutable collection instance with a predefined set of values. It’s usually preferable to have those predefined values be in an immutable collection, and then to initialize the mutable collection via a copy constructor.

Program to interfaces, not to implementations

You said you’ve declared the list as an ArrayList in your code, but you should only do that if you’re using some member of ArrayList that’s not in List .

Which you are most likely not doing.

Usually you should just declare variables by the most general interface that you are going to use (e.g. Iterable , Collection , or List ), and initialize them with the specific implementation (e.g. ArrayList , LinkedList or Arrays.asList() ).

Otherwise you’re limiting your code to that specific type, and it’ll be harder to change when you want to.

Читайте также:  Конфигурация php ini mysql

For example, if you’re passing an ArrayList to a void method(. ) :

// Iterable if you just need iteration, for (String s : strings): void method(Iterable strings) < for (String s : strings) < . >> // Collection if you also need .size(), .isEmpty(), or .stream(): void method(Collection strings) < if (!strings.isEmpty()) < strings.stream(). >> // List if you also need random access, .get(index): void method(List strings) < strings.get(. ) >// Don't declare a specific list implementation // unless you're sure you need it: void method(ArrayList strings) < . // You don't want to limit yourself to just ArrayList >

Another example would be always declaring variable an InputStream even though it is usually a FileInputStream or a BufferedInputStream , because one day soon you or somebody else will want to use some other kind of InputStream .

Источник

ArrayList initialization equivalent to array initialization [duplicate]

Is there a way to do the same thing with an ArrayList? Or must I add the contents individually with array.add() ?

8 Answers 8

new ArrayList(Arrays.asList(1,2,3,5,8,13,21)); 

It’s worth mentioning that unless you strictly need an ArrayList it’s probably better to just use the List that’s returned by Arrays#asList .

The list returned by Arrays.asList() is NOT unmodifiable, @kocko. It has a fixed size, but you can change the references to point to entirely different objects like Arrays.asList(. ).set(0,new String(«new string»)) This code will work and set the first element of the list to the String object with value «new string». And in fact, it writes through to the native array! Definitely not unmodifiable.

Because a well configured IDE will write the imports for you, as long as there is a single matching class, as is the case here.

What this is actually doing is creating a class derived from ArrayList (the outer set of braces do this) and then declare a static initialiser (the inner set of braces). This is actually an inner class of the containing class, and so it’ll have an implicit this pointer. Not a problem unless you want to serialise it, or you’re expecting the outer class to be garbage collected.

I understand that Java 7 will provide additional language constructs to do precisely what you want.

EDIT: recent Java versions provide more usable functions for creating such collections, and are worth investigating over the above (provided at a time prior to these versions)

Not my downvote, but I consider this a pretty nasty abuse of anonymous classes. At least you’re not trying to pass it off as a special feature.

I don’t believe that creating an anonymous class is bad in itself. You should be aware of it though.

I’m guessing that it keeps getting downvoted because it does just what the OP wanted to avoid: using add() for each element.

I would consider downvoting, because creating a class, just to initialize a single object, strikes me as overkill. But I’m not sufficiently an expert in java to know whether this is a bad thing to do. Maybe creating thousands of unnecessary classes, in a large program, is considered good java coding? Its also horrendously verbose, if there are many elements. Is there any advantage to this approach, versus other proposed answers?

Читайте также:  Php дата название месяца

It might have been downvoted because it only works for final values. I agree your solution does work for what the question asked, but you know some people are on StackOverflow.

Here is the closest you can get:

ArrayList list = new ArrayList(Arrays.asList("Ryan", "Julie", "Bob")); 

You can go even simpler with:

List list = Arrays.asList("Ryan", "Julie", "Bob") 

Looking at the source for Arrays.asList, it constructs an ArrayList, but by default is cast to List. So you could do this (but not reliably for new JDKs):

ArrayList list = (ArrayList)Arrays.asList("Ryan", "Julie", "Bob") 

The ArrayList constructed by asList is not a java.util.ArrayList, only shares the same. In fact, it cannot be, as the return value of asList is specified to be a fixed size list, but an ArrayList must be of variable size.

Arrays.asList("Ryan", "Julie", "Bob"); 

Well, in Java there’s no literal syntax for lists, so you have to do .add().

If you have a lot of elements, it’s a bit verbose, but you could either:

2 would look something like:

String[] elements = new String[] ; List list = new ArrayList(Arrays.asList(elements)); 

This results in some unnecessary object creation though.

The selected answer is: ArrayList(Arrays.asList(1,2,3,5,8,13,21));

However, its important to understand the selected answer internally copies the elements several times before creating the final array, and that there is a way to reduce some of that redundancy.

Lets start by understanding what is going on:

  1. First, the elements are copied into the Arrays.ArrayList created by the static factory Arrays.asList(T. ) . This does not the produce the same class as java.lang.ArrayList despite having the same simple class name. It does not implement methods like remove(int) despite having a List interface. If you call those methods it will throw an UnspportedMethodException . But if all you need is a fixed-sized list, you can stop here.
  2. Next the Arrays.ArrayList constructed in #1 gets passed to the constructor ArrayList<>(Collection) where the collection.toArray() method is called to clone it.
public ArrayList(Collection collection)
if (a.getClass() != Object[].class) < //Arrays.asList(T. ) is always true here //when T subclasses object Object[] newArray = new Object[a.length]; System.arraycopy(a, 0, newArray, 0, a.length); a = newArray; >array = a; size = a.length; 

Thus, our data was copied 3x just to explicitly initialize the ArrayList. We could get it down to 2x if we force Arrays.AsList(T. ) to construct an Object[] array, so that ArrayList can later adopt it, which can be done as follows:

(List)(List) new ArrayList<>(Arrays.asList((Object) 1, 2 ,3, 4, 5)); 

Or maybe just adding the elements after creation might still be the most efficient.

Источник

Оцените статью