5

Is there a way of appending an object to a list and returning the result in one line in a functional non-imperative way? How would you do it if also the original list should not be mutated? Java 8 is allowed.

I already know how to concat two lists in one line. (Source)

List listAB = Stream.concat(listA.stream(), listB.stream()).collect(Collectors.toList());

I also know how to make a list out of objects in one line.

List listO1 = Collections.singletonList(objectA);
List listO2 = Stream.of(objectA, objectB).collect(Collectors.toList());
List listOO = Arrays.asList(objectA, objectB);

Is there anything better than replacing listB in the first line with a part of the following lines?

Community
  • 1
  • 1
mxscho
  • 1,586
  • 1
  • 12
  • 25
  • have you tried listA.clone().append(objectB) ? – bracco23 Dec 09 '16 at 23:56
  • @bracco23 The `List` interface does not expose an `append(...)` method, does it?. – mxscho Dec 10 '16 at 00:01
  • 2
    It doesn't expose a clone() either. – JB Nizet Dec 10 '16 at 00:04
  • @JBNizet I know, but I didn't mention it because it is not far from reality to assume that I could be working with the actual object and not a variable of type `List`. – mxscho Dec 10 '16 at 00:08
  • @mxscho you're right it doesn't, but it expose add(...) and the JavaDoc says that the element added goes to the end of the list. Same behaviour, different name. – bracco23 Dec 10 '16 at 15:55
  • And it doesn't expose clone either, but Object does, and it is safe to assume it is overriden such as its behaviour is consistent. – bracco23 Dec 10 '16 at 15:57

2 Answers2

15

You could use

List<Foo> newList = 
    Stream.concat(list.stream(), Stream.of(fooToAdd))
          .collect(Collectors.toList());

Bt I find this a little bit convoluted. Strive for readability rather than finding single-line, more obscure solutions. Also, never use raw types as you're doing in your question.

JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174
  • Sure about the raw types. I didn't want to bloat the question even if I see that it might be confusing or unusual. I guess your answer is the way to go for me right now, but I thought there might be something better. – mxscho Dec 10 '16 at 00:05
  • 2
    That's 3 **lines**. Sure it's only one *statement*, but that wasn't the question. ;-) 2 statement, 1 line answer [here](http://stackoverflow.com/a/41071051/5221149). Haven't decided yet, if my answer is a joke or not. – Andreas Dec 10 '16 at 00:57
  • @Andreas While it's somehow funny, it's not a joke. However, by continuing to complain about the other solutions you're forcing me to edit my question to match everyones thought process (one line = one statement = functional, not imperative). I don't want to do that because it would invalidate your answer (and I thought it's clear what I meant). Furthermore, this answer is still not something new to me, I also mentioned it half-way in the question (could be because there is no other good solution). I think I'll wait one more day before accepting it. – mxscho Dec 10 '16 at 05:20
  • 2
    @mxscho That wasn't a *complaint*. It's an observation, aka a comment to JB that although he answered the *spirit* of your question, he didn't answer the *letter* of your question. And he did answer, because the code in your question is for concatenating two lists, but your question is about how to add a single element to a list, and this answer shows how to adjust the code *you* showed, to actually do that. – Andreas Dec 10 '16 at 18:48
  • @Andreas I explicitely asked in the last sentence if there's another better way of doing it other than just putting my statements together hence this answer is not quite (even if taken literally) what I was looking for because I basically already knew that myself. I'm still not sure if there is something that would satisfy me at all of course. That's why I asked in the first place. Quibbling doesn't help me either, I'm sorry for the bad specification. Neither am I a native speaker nor did I mean to insult anyone by using the word _complain_ instead of _comment_. Edited it to match my spirit. – mxscho Dec 10 '16 at 21:33
3

You can use var args and create a stream from it to be appended to the stream of the actual list, e.g:

public static <T> List<T> append(List<T> list, T... args){
    return Stream.concat(list.stream(), Stream.of(args))
            .collect(Collectors.toList());
}
Darshan Mehta
  • 27,835
  • 7
  • 53
  • 81