Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public interface ImmutableList<T extends @Nullable Object>
/// @param list the list to wrap
/// @return an ImmutableList containing the elements of the input list
static <T extends @Nullable Object> ImmutableList<T> fromList(List<T> list) {
return new ImmutableListList<>(list);
return new ImmutableListList<>(new ArrayList<>(list));
}

/// Creates an [ImmutableList] from an array.
Expand All @@ -123,6 +123,18 @@ public interface ImmutableList<T extends @Nullable Object>
/// @param array the array to wrap
/// @return an ImmutableList containing the elements of the input array
static <T extends @Nullable Object> ImmutableList<T> fromArray(T[] array) {
return new ImmutableListArray<>(array.clone());
}

/// Creates an [ImmutableList] from an array.
///
/// This method wraps the given array in an immutable wrapper.
///
/// @param <T> the element type
/// @param array the array to wrap
/// @return an ImmutableList containing the elements of the input array
static <T extends @Nullable Object> ImmutableList<T> fromItems(T... array) {
// weigl: copy needed, array dynamical created and not leaked.
return new ImmutableListArray<>(array);
}

Expand Down Expand Up @@ -246,7 +258,8 @@ default ImmutableList<T> prependReverse(Iterable<T> collection) {
/// @param array the array to prepend
/// @return a new list with the array's elements at the beginning
default ImmutableList<T> prepend(T... array) {
return new ImmutableListConcat<>(ImmutableList.fromArray(array), this);
// weigl: here we can use the leaky version
return new ImmutableListConcat<>(new ImmutableListArray<>(array), this);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think we use this here. See the added test cases ...

}

/// Appends a single element to this list.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@
final class ImmutableListArray<T extends @Nullable Object> implements ImmutableList<T> {
private final T[] data;

public ImmutableListArray(T[] data) {
/**
* Caution: This constructor does *not* the argument array but refers to it directly.
* Do not call it but from contexts where you know that data remains unmodified.
*
* @see ImmutableList#fromArray(Object[])
* @param data the array data
*/
ImmutableListArray(T[] data) {
this.data = data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,41 @@ public static Integer[] create(int i) {
return IntStream.range(1, i + 1).boxed().toArray(Integer[]::new);
}

@Test
void immutability1() {
Integer[] array = { 0, 1, 4 };
// constructor does not copy the array, so changes to the array are reflected in the list
// While this seems dangerous, the constructur is package-private and thus considered safe.
ImmutableListArray<Integer> list = new ImmutableListArray<>(array);
assertThat(list.get(2)).isEqualTo(4);
array[2] = 2;
assertThat(list.get(2)).isEqualTo(2);
}

@Test
void immutability2() {
Integer[] array = { 0, 1, 4 };
ImmutableList<Integer> list = ImmutableList.fromArray(array);
array[2] = 2;
assertThat(list.get(2)).isEqualTo(4);
}

@Test
void immutability3() {
Integer[] array = { 0, 1, 4 };
ImmutableList<Integer> list = ImmutableList.fromItems(array);
array[2] = 2;
assertThat(list.get(2)).isEqualTo(4);
}

@Test
void immutability4() {
Integer[] array = { 0, 1, 4 };
ImmutableList<Integer> list = ImmutableList.fromItems(-1).prepend(array);
assertThat(list.get(2)).isEqualTo(4);
array[2] = 2;
assertThat(list.get(2)).isEqualTo(4);
}

@Test
void size() {
Expand Down
Loading