3

I am new with Stream API and I am looking for more elegant and shortest way to fill an ArrayList with the same object using Stream API equivalent to this code:

SomeObject someObject = new SomeObject();
List<SomeObject> someObjectList = new ArrayList<>();

int maxLimitValue = 70; //for example
for(int i=0; i<=maxLimitValue; i++){
   someObjectList.add(someObject);
}

I have seen many different solutions for my current task:

This variant is almost what I want, but there is an auto-generation of the objects, but I need to use the same object created once.

This solution is also almost what I need, but I am no sure about this copying of objects and the returned List type is not ArrayList (it returned the CopiesList type, which cannot be added to the ArrayList in the future operations).

p.s. maybe it's possible duplicate, but I really can't find the correct and short way to do this using Stream API.

Update (assylias additions):

Yes, I agree with you about this variant:

List<SomeObject> list = Collections.nCopies(70, someObject);

But, when I am opening this method:

public static <T> List<T> nCopies(int n, T o) {
        if (n < 0)
            throw new IllegalArgumentException("List length = " + n);
        return new CopiesList<>(n, o);
    }

And as we see - it returning the CopiesList object, not ArrayList. Also, as the other lists, it is extending the AbstractList:

private static class CopiesList<E>
        extends AbstractList<E>
        implements RandomAccess, Serializable
    {
        private static final long serialVersionUID = 2739099268398711800L;

        final int n;
        final E element;

        CopiesList(int n, E e) {
            assert n >= 0;
            this.n = n;
            element = e;
        }
...}

It's not quite ArrayList, but thank's for your suggestions and advice whithout an empty words and off-topic comments, I will use your solution.

Community
  • 1
  • 1
Alexey Shabramov
  • 730
  • 1
  • 16
  • 37
  • 2
    The second link you posted (`List list = new ArrayList(Collections.nCopies(60, 0))`) does exactly what you need, and it does create an `ArrayList`. – Eran Oct 26 '16 at 09:20
  • 2
    What's the point of storing 70 times a reference on the same object ? – Spotted Oct 26 '16 at 09:25
  • Spotted, this is the one large solution to solve some JavaFX issue in the TableView+Pagination integration with Hibernate and Spring (70 is for example, only). It is a very long time to explain about this issue. – Alexey Shabramov Oct 26 '16 at 09:31

2 Answers2

8

You can build the stream manually:

List<SomeObject> list = Stream.generate(() -> someObject).limit(70).collect(toList());
//or if you want to make sure you get an ArrayList:
List<SomeObject> list = Stream.generate(() -> someObject).limit(70).collect(toCollection(ArrayList::new));

Although creating a stream just for that purpose is probably inefficient and I would probably go with what @Eran suggested:

List<SomeObject> list = Collections.nCopies(70, someObject);
//or if you want to make sure you get an ArrayList:
List<SomeObject> list = new ArrayList<> (Collections.nCopies(70, someObject));
assylias
  • 321,522
  • 82
  • 660
  • 783
  • Thank's for your answer, I have updated the question, maybe you can add something to this part? – Alexey Shabramov Oct 26 '16 at 10:13
  • 2
    You can always write `new ArrayList<> (Collections.nCopies(70, someObject))` but why do you want an ArrayList? – assylias Oct 26 '16 at 10:53
  • When I am trying to add to this list (list created from nCopies) another list(another ArrayList) by method addAll() - I am getting an UnsupportedOperationException, but if I adding list from nCopies to another - all is working fine, so I think you were right - it's not a point now. Thank's a lot! Really helped! – Alexey Shabramov Oct 26 '16 at 11:01
  • 2
    Note that the stream solution using the `toList()` collector *happens* to return an `ArrayList`, but doesn’t guaranty it. You’ll have to use `toCollection(ArrayList::new)`, if it really has to be a an `ArrayList`. But even using streams, `Collections.nCopies(70, someObject).stream()` is the potentially more efficient stream source. It’s equivalent to `IntStream.range(0, 70).mapToObj(i -> someObject)`… – Holger Oct 27 '16 at 10:04
0

You can basically use IntStream.range() and map every int to the same object with mapToObj method and collect it to a list

Louis F.
  • 2,018
  • 19
  • 22