Shuffle list except for certain sequences - java

I want to shuffle an ArrayList but based on some custom conditions:
if my array list was something like [1, 4, 5, 6, 9, 45, 67],
I want to shuffle it but make sure 5, 6, 9 always appear together.
Is there any method available in Collections class to do this?
I have tried doing this, but it throws ConcurrentModificationException
List<Integer> y= new ArrayList<>();
y.add(1);
y.add(4);
y.add(5);
y.add(6);
y.add(9);
y.add(45);
y.add(67);
List<Integer> z = y.subList(2, 5);
y.removeAll(z);
Collections.shuffle(y);
int index = ThreadLocalRandom.current()
.nextInt(0, y.size() + 1);
y.addAll(index,z);

It sounds like your data should really be a list of lists, especially since its likely that you will have more than 1 group that needs to stay together.
You can always flatten it when you need.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<List<Integer>> y = new ArrayList<List<Integer>>();
y.add(new ArrayList<Integer>(Arrays.asList(1)));
y.add(new ArrayList<Integer>(Arrays.asList(4)));
y.add(new ArrayList<Integer>(Arrays.asList(5, 6, 9)));
y.add(new ArrayList<Integer>(Arrays.asList(45)));
y.add(new ArrayList<Integer>(Arrays.asList(67)));
Collections.shuffle(y);
List<Integer> flatList = new ArrayList<>();
y.forEach(flatList::addAll);
}
}

A simple way of doing this is to store your target elements in a separate List:
List<Integer> target = new ArrayList<>();
target.add(5);
target.add(6);
target.add(9);
Then shuffle your main list:
Collections.shuffle(y);
Then get a random number from 0 -> y.size().
Random ran = new Random();
int pos = ran.nextInt(y.size());
And insert your target list into your original list:
y.addAll(pos, target);
Note: this assumes your original list has the target 3 numbers removed already.

Without seeing your code, I'd think that the ConcurrentModificationExceptions are thrown because you try to remove the group elements from the list or to add them back in while iterating it. Changing a collection while iterating it leads to those exceptions: Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop.
It will get a lot easier if you do not treat the groups as the exception, but as the norm. What I mean by this is that you should convert your List<?> into a List<List<?>> where each sub list contains either one element or one of the groups. You can then shuffle that list easily with Collections.shuffle() and flatten it again.
Look at this rough implementation:
List<Integer> ints = new ArrayList<>(asList(2, 3, 5, 4, 8, 7, 11, 55));
List<List<Integer>> groups = asList(asList(5, 4), asList(7, 11));
// remove all the grouped elements from the list
groups.forEach(ints::removeAll);
// wrap the single elements into list and join them with the groups
List<List<Integer>> wrapped = Stream.concat(ints.stream().map(Arrays::asList),
groups.stream())
.collect(Collectors.toList());
Collections.shuffle(wrapped);
// flatten the list into single elements again
List<Integer> shuffled = wrapped.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
System.out.println(shuffled); // e.g. [55, 3, 7, 11, 2, 8, 5, 4]
// ----- ----
Note that while this is quite readable, it is probably not the most efficient or error proof solution. But it should give you an idea how to tackle the problem.
Edit after comment from Gonen I. Here is a helper method to only remove the exact sequences and not random parts of them all over the list:
private static <T> void removeSequence(List<T> list, List<T> sequence)
{
int indexOfSubList = Collections.lastIndexOfSubList(list, sequence);
while (indexOfSubList != -1)
{
for (int j = 0; j < sequence.size(); j++)
{
list.remove(indexOfSubList);
}
indexOfSubList = Collections.lastIndexOfSubList(list, sequence);
}
}
Use it by replacing groups.forEach(ints::removeAll); by groups.forEach(group -> removeSequence(ints, group));

Related

Problem when working with arrays in Java - code does not go inside the "if" statement [duplicate]

How do I convert an array to a list in Java?
I used the Arrays.asList() but the behavior (and signature) somehow changed from Java SE 1.4.2 (docs now in archive) to 8 and most snippets I found on the web use the 1.4.2 behaviour.
For example:
int[] numbers = new int[] { 1, 2, 3 };
Arrays.asList(numbers)
on 1.4.2 returns a list containing the elements 1, 2, 3
on 1.5.0+ returns a list containing the array 'numbers'
In many cases it should be easy to detect, but sometimes it can slip unnoticed:
Assert.assertTrue(Arrays.asList(numbers).indexOf(4) == -1);
In your example, it is because you can't have a List of a primitive type. In other words, List<int> is not possible.
You can, however, have a List<Integer> using the Integer class that wraps the int primitive. Convert your array to a List with the Arrays.asList utility method.
Integer[] numbers = new Integer[] { 1, 2, 3 };
List<Integer> list = Arrays.asList(numbers);
See this code run live at IdeOne.com.
In Java 8, you can use streams:
int[] numbers = new int[] { 1, 2, 3 };
Arrays.stream(numbers)
.boxed()
.collect(Collectors.toList());
We cannot have List<int> as int is a primitive type so we can only have List<Integer>.
Java 16
Java 16 introduces a new method on Stream API called toList(). This handy method returns an unmodifiable List containing the stream elements. So, trying to add a new element to the list will simply lead to UnsupportedOperationException.
int[] ints = new int[] {1,2,3,4,5};
Arrays.stream(ints).boxed().toList();
Java 8 (int array)
int[] ints = new int[] {1,2,3,4,5};
List<Integer> list11 =Arrays.stream(ints).boxed().collect(Collectors.toList());
Java 8 and below (Integer array)
Integer[] integers = new Integer[] {1,2,3,4,5};
List<Integer> list21 = Arrays.asList(integers); // returns a fixed-size list backed by the specified array.
List<Integer> list22 = new ArrayList<>(Arrays.asList(integers)); // good
List<Integer> list23 = Arrays.stream(integers).collect(Collectors.toList()); //Java 8 only
Need ArrayList and not List?
In case we want a specific implementation of List e.g. ArrayList then we can use toCollection as:
ArrayList<Integer> list24 = Arrays.stream(integers)
.collect(Collectors.toCollection(ArrayList::new));
Why list21 cannot be structurally modified?
When we use Arrays.asList the size of the returned list is fixed because the list returned is not java.util.ArrayList, but a private static class defined inside java.util.Arrays. So if we add or remove elements from the returned list, an UnsupportedOperationException will be thrown. So we should go with list22 when we want to modify the list. If we have Java8 then we can also go with list23.
To be clear list21 can be modified in sense that we can call list21.set(index,element) but this list may not be structurally modified i.e. cannot add or remove elements from the list. You can also check this answer of mine for more explanation.
If we want an immutable list then we can wrap it as:
List<Integer> list22 = Collections.unmodifiableList(Arrays.asList(integers));
Another point to note is that the method Collections.unmodifiableList returns an unmodifiable view of the specified list. An unmodifiable view collection is a collection that is unmodifiable and is also a view onto a backing collection. Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view.
We can have a truly immutable list in Java 9 and 10.
Truly Immutable list
Java 9:
String[] objects = {"Apple", "Ball", "Cat"};
List<String> objectList = List.of(objects);
Java 10 (Truly Immutable list):
We can use List.of introduced in Java 9. Also other ways:
List.copyOf(Arrays.asList(integers))
Arrays.stream(integers).collect(Collectors.toUnmodifiableList());
Speaking about conversion way, it depends on why do you need your List.
If you need it just to read data. OK, here you go:
Integer[] values = { 1, 3, 7 };
List<Integer> list = Arrays.asList(values);
But then if you do something like this:
list.add(1);
you get java.lang.UnsupportedOperationException.
So for some cases you even need this:
Integer[] values = { 1, 3, 7 };
List<Integer> list = new ArrayList<Integer>(Arrays.asList(values));
First approach actually does not convert array but 'represents' it like a List. But array is under the hood with all its properties like fixed number of elements. Please note you need to specify type when constructing ArrayList.
The problem is that varargs got introduced in Java 5 and unfortunately, Arrays.asList() got overloaded with a vararg version too. So Arrays.asList(numbers) is understood by the Java 5 compiler as a vararg parameter of int arrays.
This problem is explained in more details in Effective Java 2nd Ed., Chapter 7, Item 42.
I recently had to convert an array to a List. Later on the program filtered the list attempting to remove the data. When you use the Arrays.asList(array) function, you create a fixed size collection: you can neither add nor delete. This entry explains the problem better than I can: Why do I get an UnsupportedOperationException when trying to remove an element from a List?.
In the end, I had to do a "manual" conversion:
List<ListItem> items = new ArrayList<ListItem>();
for (ListItem item: itemsArray) {
items.add(item);
}
I suppose I could have added conversion from an array to a list using an List.addAll(items) operation.
Even shorter:
List<Integer> list = Arrays.asList(1, 2, 3, 4);
Using Arrays
This is the simplest way to convert an array to List. However, if you try to add a new element or remove an existing element from the list, an UnsupportedOperationException will be thrown.
Integer[] existingArray = {1, 2, 3};
List<Integer> list1 = Arrays.asList(existingArray);
List<Integer> list2 = Arrays.asList(1, 2, 3);
// WARNING:
list2.add(1); // Unsupported operation!
list2.remove(1); // Unsupported operation!
Using ArrayList or Other List Implementations
You can use a for loop to add all the elements of the array into a List implementation, e.g. ArrayList:
List<Integer> list = new ArrayList<>();
for (int i : new int[]{1, 2, 3}) {
list.add(i);
}
Using Stream API in Java 8
You can turn the array into a stream, then collect the stream using different collectors: The default collector in Java 8 use ArrayList behind the screen, but you can also impose your preferred implementation.
List<Integer> list1, list2, list3;
list1 = Stream.of(1, 2, 3).collect(Collectors.toList());
list2 = Stream.of(1, 2, 3).collect(Collectors.toCollection(ArrayList::new));
list3 = Stream.of(1, 2, 3).collect(Collectors.toCollection(LinkedList::new));
See also:
Why do we use autoboxing and unboxing in Java?
When to use LinkedList over ArrayList?
Another workaround if you use Apache commons-lang:
int[] numbers = new int[] { 1, 2, 3 };
Arrays.asList(ArrayUtils.toObject(numbers));
Where ArrayUtils.toObject converts int[] to Integer[]
In Java 9 you have the even more elegant solution of using immutable lists via the new convenience factory method List.of:
List<String> immutableList = List.of("one","two","three");
(shamelessly copied from here )
One-liner:
List<Integer> list = Arrays.asList(new Integer[] {1, 2, 3, 4});
If you are targeting Java 8 (or later), you can try this:
int[] numbers = new int[] {1, 2, 3, 4};
List<Integer> integers = Arrays.stream(numbers)
.boxed().collect(Collectors.<Integer>toList());
NOTE:
Pay attention to the Collectors.<Integer>toList(), this generic method helps you to avoid the error "Type mismatch: cannot convert from List<Object> to List<Integer>".
you have to cast in to array
Arrays.asList((Object[]) array)
Using Guava:
Integer[] array = { 1, 2, 3};
List<Integer> list = Lists.newArrayList(sourceArray);
Using Apache Commons Collections:
Integer[] array = { 1, 2, 3};
List<Integer> list = new ArrayList<>(6);
CollectionUtils.addAll(list, array);
I've had the same problem and wrote a generic function that takes an array and returns an ArrayList of the same type with the same contents:
public static <T> ArrayList<T> ArrayToArrayList(T[] array) {
ArrayList<T> list = new ArrayList<T>();
for(T elmt : array) list.add(elmt);
return list;
}
Given Array:
int[] givenArray = {2,2,3,3,4,5};
Converting integer array to Integer List
One way: boxed() -> returns the IntStream
List<Integer> givenIntArray1 = Arrays.stream(givenArray)
.boxed()
.collect(Collectors.toList());
Second Way: map each element of the stream to Integer and then collect
NOTE:
Using mapToObj you can covert each int element into string stream, char stream etc by casing i to (char)i
List<Integer> givenIntArray2 = Arrays.stream(givenArray)
.mapToObj(i->i)
.collect(Collectors.toList());
Converting One array Type to Another Type Example:
List<Character> givenIntArray2 = Arrays.stream(givenArray)
.mapToObj(i->(char)i)
.collect(Collectors.toList());
So it depends on which Java version you are trying-
Java 7
Arrays.asList(1, 2, 3);
OR
final String arr[] = new String[] { "G", "E", "E", "K" };
final List<String> initialList = new ArrayList<String>() {{
add("C");
add("O");
add("D");
add("I");
add("N");
}};
// Elements of the array are appended at the end
Collections.addAll(initialList, arr);
OR
Integer[] arr = new Integer[] { 1, 2, 3 };
Arrays.asList(arr);
In Java 8
int[] num = new int[] {1, 2, 3};
List<Integer> list = Arrays.stream(num)
.boxed().collect(Collectors.<Integer>toList())
Reference - http://www.codingeek.com/java/how-to-convert-array-to-list-in-java/
Can you improve this answer please as this is what I use but im not 100% clear. It works fine but intelliJ added new WeatherStation[0]. Why the 0 ?
public WeatherStation[] removeElementAtIndex(WeatherStation[] array, int index)
{
List<WeatherStation> list = new ArrayList<WeatherStation>(Arrays.asList(array));
list.remove(index);
return list.toArray(new WeatherStation[0]);
}
Use this to convert an Array arr to List.
Arrays.stream(arr).collect(Collectors.toList());
An example of defining a generic method to convert an array to a list:
public <T> List<T> fromArrayToList(T[] a) {
return Arrays.stream(a).collect(Collectors.toList());
}
use two line of code to convert array to list if you use it in integer value
you must use autoboxing type for primitive data type
Integer [] arr={1,2};
List<Integer> listInt=Arrays.asList(arr);
As of Java 8, the following should do
int[] temp = {1, 2, 3, 4, 5};
List<Integer> tempList = Arrays.stream(temp).boxed().collect(Collectors.toList());
If you are trying to optimize for memory, etc., (and don't want to pull in external libraries) it's simpler than you think to implement your own immutable "array view list" – you just need to extend java.util.AbstractList.
class IntArrayViewList extends AbstractList<Integer> {
int[] backingArray;
int size;
IntArrayViewList(int[] backingArray, int size) {
this.backingArray = backingArray;
this.size = size;
}
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int i = 0;
#Override
public boolean hasNext() {
return i < size;
}
#Override
public Integer next() {
return get(i++);
}
};
}
public int size() {
return size;
}
public Integer get(int i) {
return backingArray[i];
}
}
int is a primitive. Primitives can’t accept null and have default value. Hence, to accept null you need to use wrapper class Integer.
Option 1:
int[] nos = { 1, 2, 3, 4, 5 };
Integer[] nosWrapped = Arrays.stream(nos).boxed()   
.toArray(Integer[]::new);
nosWrapped[5] = null // can store null
Option 2:
You can use any data structure that uses the wrapper class Integer
int[] nos = { 1, 2, 3, 4, 5 };
List<Integer> = Arrays.asList(nos)
I started looking at this by trying to reduce the amount of code preparing the input of some test cases. I see a lot of effort around trying to include advanced and new features along with Arrays.asList(), but below the code chosen due simplicity:
//Integer input[]
List<Integer> numbers = Arrays.asList(new Integer[]{1, 2 ,3, 4, 5, 4, 3, 2, 1, 3, 4});
//String input[]
List<String> names = Arrays.asList(new String[]{"Jhon", "Lucas", "Daniel", "Jim", "Sam"});
//String input[]
List<Character> letters = Arrays.asList(new Character[]{'A', 'B', 'K', 'J', 'F'});
Please notice that Anonymous array example will work just with Arrays of Non Primitive Types as the API uses Generics, that's the reason you can see several 2 line examples around, more info here: Why don't Java Generics support primitive types?
For newer JDKs there is another simpler option, the below examples are equivalent to the ones show above:
//Integer
List<Integer> numbers = Arrays.asList(1, 2 ,3, 4, 5, 4, 3, 2, 1, 3, 4);
//String
List<String> names = Arrays.asList("Jhon", "Lucas", "Daniel", "Jim", "Sam");
//Character
List<Character> letters = Arrays.asList('A', 'B', 'K', 'J', 'F');

remove duplicate list from an arrayList using Set

I have a List that contains duplicate ArrayList.
I'm looking for a solution to remove them.
Here is an example:
listOne = [[1, 0], [0, 1], [3, 2], [2, 3]]
This set contains duplicate List. Normally i want to get :
theListAfterTransformation = [[1, 0],[3, 2]]
Here is my tiny example, i tried to use the Set but it didn't work well.
public class Example {
public static void main( String[] args ) {
ArrayList<ArrayList<Integer>> lists = new ArrayList<>();
ArrayList<Integer> list1 = new ArrayList<>(); list1.add(1); list1.add(0);
ArrayList<Integer> list2 = new ArrayList<>(); list2.add(0); list2.add(1);
ArrayList<Integer> list3 = new ArrayList<>(); list3.add(3); list3.add(2);
ArrayList<Integer> list4 = new ArrayList<>(); list4.add(2); list4.add(3);
lists.add(list1);lists.add(list2);lists.add(list3);lists.add(list4);
System.out.println(getUnduplicateList(lists));
}
public static ArrayList<ArrayList<Integer>> getUnduplicateList( ArrayList<ArrayList<Integer>> lists) {
Iterator iterator = lists.iterator();
Set<ArrayList<Integer>> set = new HashSet<>();
while (iterator.hasNext()){
ArrayList<Integer> list = (ArrayList<Integer>) iterator.next();
set.add(list);
}
return new ArrayList<>(set);
}
}
Note that is a tiny example from my project and it will be very hard to use a solution that change many thing in this implementation.
So take into account that the getUnduplicateList should keep the same signature. the good idea will be to change only the implementation.
This program print the same list as the input. any idea please.
A couple notes on terminology—Set is a distinct data structure from List, where the former is unordered and does not allow duplicates, while the latter is a basic, linear collection, that's generally ordered, and allows duplicates. You seem to be using the terms interchangeably, which may be part of the issue you're having: Set is probably the appropriate data structure here.
That said, it seems that your code is relying on the List API, so we can follow that along. Note that you should, in general, code to the interface (List), rather than the specific class (ArrayList).
Additionally, consider using the Arrays.asList shorthand method for initializing a list (note that this returns an immutable list).
Finally, note that a HashSet eliminates duplicates by checking if both objects have the same hashCode. Lists containing the same elements are still not considered to be the same list unless the elements appear in the same order, and will typically not be treated as duplicates. Sets, however, implement equals and hashCode in such a way that two sets containing exactly the same elements are considered equal (order doesn't matter).
Using your original starting collection, you can convert each inner-list to a set. Then, eliminate duplicates from the outer collection. Finally, convert the inner-collections back to lists, to maintain compatibility with the rest of your code (if needed). This approach will work regardless of the size of the inner-lists.
You can simulate these steps using a Stream, and using method references to convert to and from the Set, as below.
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.stream.Collectors;
public class Example {
public static void main( String[] args ) {
List<Integer> list1 = Arrays.asList(1, 0);
List<Integer> list2 = Arrays.asList(0, 1);
List<Integer> list3 = Arrays.asList(3, 2);
List<Integer> list4 = Arrays.asList(2, 3);
List<List<Integer>> lists = Arrays.asList(list1, list2, list3, list4);
System.out.println(getUnduplicateList(lists));
}
public static List<List<Integer>> getUnduplicateList(List<List<Integer>> lists) {
return lists
.stream()
.map(HashSet::new)
.distinct()
.map(ArrayList::new)
.collect(Collectors.toList());
}
}
You need to convert the inner lists to sets as well.
Another solution is to sort your lists and then run them through distinct Although this is not very efficient and you will also obtain a set of sorted lists:
Set<List<Integer>> collect = set.stream()
.map(list -> {
list.sort(Comparator.comparingInt(Integer::intValue));
return list;
})
.distinct()
.collect(Collectors.toSet());

Finding multiple min/max using Collections.min/max

In an example I was working on, I was trying to find the smallest three elements in a list (without sorting the list) and then add those three elements into a new list.
Because it was an example I could just simple use a for loop, use Collections.min(list) add that element to the new list, then remove that element from the original list. If I had not removed the element, I would get the same element three times. However, by removing the element, I got my desired outcome.
How can I do this without removing the max/min elements from the list?
If you want to find the max/min 3 elements, I would suggest you to use a PriorityQueue:
PriorityQueue<Integer> pq = new PriorityQueue<>(k);
And then in a loop, add elements to this queue.
And then you can add these 3 elements to the list by removing from the queue and simply return from the method.
Even better would be to use 3 seperate variables and directly loop on the main list. Note: this method will not be feasible if you later on update 3 to some other value. Whereas PriorityQueue approach will be flexible.
public static void main (String[] args) throws java.lang.Exception {
Integer arr[] = {2, 6, 5, 3, 7, 9, 12, 35, 1, 3};
List<Integer> incoming = Arrays.asList(arr);
Comparator<Integer> maxFirstComparator = (x, y) -> Integer.compare(y,x);
printList(getMinOrMaxKNumbers(incoming, 3, null));
System.out.println();
printList(getMinOrMaxKNumbers(incoming, 3, maxFirstComparator));
}
/*
* gets the max/min K elements from the List
* #param comparator if null is passed the method uses natural ordering
*
*/
private static List<Integer> getMinOrMaxKNumbers(List<Integer> incoming, int k, Comparator<Integer> comparator) {
int n = incoming.size();
PriorityQueue<Integer> pq = comparator == null ? new PriorityQueue<>(n) : new PriorityQueue<>(n, comparator);
for (int i : incoming) {
pq.add(i);
}
List<Integer> outgoing = new ArrayList<>(k);
for (int i = 0; i < k; i++) {
outgoing.add(pq.poll());
}
return outgoing;
}
private static void printList(List<Integer> list) {
list.stream().forEach(x -> System.out.print(x + " "));
}
I don't think there is any straight forward way to do this using the standard library.
The following code contains a utility method to get the set of a number of maximal elements.
It works by keeping the maximal elements in a TreeSet, to which an element is inserted only if it belongs to the maximal elements. A tree set is a good fit here because it is fast to find the minimal element, and to test if an element is contained in the set.
In this way you get good performance, and can be flexible with the number of maximal elements you want.
public class MultipleMaxElements {
public static void main(String[] args) {
List<Integer> l = List.of(4, 2, 5, 8, 2, 8, 0, 1);
System.out.println(maxElements(l, 3, Comparator.naturalOrder()));
System.out.println(maxElements(l, 3, Comparator.<Integer>naturalOrder().reversed()));
}
public static <T> Set<T> maxElements(Iterable<T> list, int nrElems, Comparator<T> cmp) {
TreeSet<T> maxSet = new TreeSet<>(cmp);
for (T elem : list) {
if (maxSet.size() < nrElems) {
maxSet.add(elem);
} else if (!maxSet.contains(elem) && cmp.compare(elem, maxSet.first()) > 0) {
maxSet.pollFirst();
maxSet.add(elem);
}
}
return maxSet;
}
}
In the question text you don't write anything about how duplicate elements in the input list should be handled. This method returns maximal unique elements.
If duplicates should be preserved then a tree based Guava multi-set could be used instead of a normal TreeSet.

Add multiple items to an already initialized arraylist in Java

My arraylist might be populated differently based on a user setting, so I've initialized it with
ArrayList<Integer> arList = new ArrayList<Integer>();
How can I add hundreds of integers without doing it one by one with arList.add(55);?
If you have another list that contains all the items you would like to add you can do arList.addAll(otherList). Alternatively, if you will always add the same elements to the list you could create a new list that is initialized to contain all your values and use the addAll() method, with something like
Integer[] otherList = new Integer[] {1, 2, 3, 4, 5};
arList.addAll(Arrays.asList(otherList));
or, if you don't want to create that unnecessary array:
arList.addAll(Arrays.asList(1, 2, 3, 4, 5));
Otherwise you will have to have some sort of loop that adds the values to the list individually.
What is the "source" of those integers? If it is something that you need to hard code in your source code, you may do
arList.addAll(Arrays.asList(1,1,2,3,5,8,13,21));
Collections.addAll is a varargs method which allows us to add any number of items to a collection in a single statement:
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5);
It can also be used to add array elements to a collection:
Integer[] arr = ...;
Collections.addAll(list, arr);
If you are looking to avoid multiple code lines to save space, maybe this syntax could be useful:
java.util.ArrayList lisFieldNames = new ArrayList() {
{
add("value1");
add("value2");
}
};
Removing new lines, you can show it compressed as:
java.util.ArrayList lisFieldNames = new ArrayList() {
{
add("value1"); add("value2"); (...);
}
};
Java 9+ now allows this:
List<Integer> arList = List.of(1,2,3,4,5);
The list will be immutable though.
In a Kotlin way;
val arList = ArrayList<String>()
arList.addAll(listOf(1,2,3,4,5))
If you needed to add a lot of integers it'd probably be easiest to use a for loop. For example, adding 28 days to a daysInFebruary array.
ArrayList<Integer> daysInFebruary = new ArrayList<>();
for(int i = 1; i <= 28; i++) {
daysInFebruary.add(i);
}
I believe scaevity's answer is incorrect. The proper way to initialize with multiple values would be this...
int[] otherList = {1,2,3,4,5};
So the full answer with the proper initialization would look like this
int[] otherList = {1,2,3,4,5};
arList.addAll(Arrays.asList(otherList));

Converting array to list in Java

How do I convert an array to a list in Java?
I used the Arrays.asList() but the behavior (and signature) somehow changed from Java SE 1.4.2 (docs now in archive) to 8 and most snippets I found on the web use the 1.4.2 behaviour.
For example:
int[] numbers = new int[] { 1, 2, 3 };
Arrays.asList(numbers)
on 1.4.2 returns a list containing the elements 1, 2, 3
on 1.5.0+ returns a list containing the array 'numbers'
In many cases it should be easy to detect, but sometimes it can slip unnoticed:
Assert.assertTrue(Arrays.asList(numbers).indexOf(4) == -1);
In your example, it is because you can't have a List of a primitive type. In other words, List<int> is not possible.
You can, however, have a List<Integer> using the Integer class that wraps the int primitive. Convert your array to a List with the Arrays.asList utility method.
Integer[] numbers = new Integer[] { 1, 2, 3 };
List<Integer> list = Arrays.asList(numbers);
See this code run live at IdeOne.com.
In Java 8, you can use streams:
int[] numbers = new int[] { 1, 2, 3 };
Arrays.stream(numbers)
.boxed()
.collect(Collectors.toList());
We cannot have List<int> as int is a primitive type so we can only have List<Integer>.
Java 16
Java 16 introduces a new method on Stream API called toList(). This handy method returns an unmodifiable List containing the stream elements. So, trying to add a new element to the list will simply lead to UnsupportedOperationException.
int[] ints = new int[] {1,2,3,4,5};
Arrays.stream(ints).boxed().toList();
Java 8 (int array)
int[] ints = new int[] {1,2,3,4,5};
List<Integer> list11 =Arrays.stream(ints).boxed().collect(Collectors.toList());
Java 8 and below (Integer array)
Integer[] integers = new Integer[] {1,2,3,4,5};
List<Integer> list21 = Arrays.asList(integers); // returns a fixed-size list backed by the specified array.
List<Integer> list22 = new ArrayList<>(Arrays.asList(integers)); // good
List<Integer> list23 = Arrays.stream(integers).collect(Collectors.toList()); //Java 8 only
Need ArrayList and not List?
In case we want a specific implementation of List e.g. ArrayList then we can use toCollection as:
ArrayList<Integer> list24 = Arrays.stream(integers)
.collect(Collectors.toCollection(ArrayList::new));
Why list21 cannot be structurally modified?
When we use Arrays.asList the size of the returned list is fixed because the list returned is not java.util.ArrayList, but a private static class defined inside java.util.Arrays. So if we add or remove elements from the returned list, an UnsupportedOperationException will be thrown. So we should go with list22 when we want to modify the list. If we have Java8 then we can also go with list23.
To be clear list21 can be modified in sense that we can call list21.set(index,element) but this list may not be structurally modified i.e. cannot add or remove elements from the list. You can also check this answer of mine for more explanation.
If we want an immutable list then we can wrap it as:
List<Integer> list22 = Collections.unmodifiableList(Arrays.asList(integers));
Another point to note is that the method Collections.unmodifiableList returns an unmodifiable view of the specified list. An unmodifiable view collection is a collection that is unmodifiable and is also a view onto a backing collection. Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view.
We can have a truly immutable list in Java 9 and 10.
Truly Immutable list
Java 9:
String[] objects = {"Apple", "Ball", "Cat"};
List<String> objectList = List.of(objects);
Java 10 (Truly Immutable list):
We can use List.of introduced in Java 9. Also other ways:
List.copyOf(Arrays.asList(integers))
Arrays.stream(integers).collect(Collectors.toUnmodifiableList());
Speaking about conversion way, it depends on why do you need your List.
If you need it just to read data. OK, here you go:
Integer[] values = { 1, 3, 7 };
List<Integer> list = Arrays.asList(values);
But then if you do something like this:
list.add(1);
you get java.lang.UnsupportedOperationException.
So for some cases you even need this:
Integer[] values = { 1, 3, 7 };
List<Integer> list = new ArrayList<Integer>(Arrays.asList(values));
First approach actually does not convert array but 'represents' it like a List. But array is under the hood with all its properties like fixed number of elements. Please note you need to specify type when constructing ArrayList.
The problem is that varargs got introduced in Java 5 and unfortunately, Arrays.asList() got overloaded with a vararg version too. So Arrays.asList(numbers) is understood by the Java 5 compiler as a vararg parameter of int arrays.
This problem is explained in more details in Effective Java 2nd Ed., Chapter 7, Item 42.
I recently had to convert an array to a List. Later on the program filtered the list attempting to remove the data. When you use the Arrays.asList(array) function, you create a fixed size collection: you can neither add nor delete. This entry explains the problem better than I can: Why do I get an UnsupportedOperationException when trying to remove an element from a List?.
In the end, I had to do a "manual" conversion:
List<ListItem> items = new ArrayList<ListItem>();
for (ListItem item: itemsArray) {
items.add(item);
}
I suppose I could have added conversion from an array to a list using an List.addAll(items) operation.
Even shorter:
List<Integer> list = Arrays.asList(1, 2, 3, 4);
Using Arrays
This is the simplest way to convert an array to List. However, if you try to add a new element or remove an existing element from the list, an UnsupportedOperationException will be thrown.
Integer[] existingArray = {1, 2, 3};
List<Integer> list1 = Arrays.asList(existingArray);
List<Integer> list2 = Arrays.asList(1, 2, 3);
// WARNING:
list2.add(1); // Unsupported operation!
list2.remove(1); // Unsupported operation!
Using ArrayList or Other List Implementations
You can use a for loop to add all the elements of the array into a List implementation, e.g. ArrayList:
List<Integer> list = new ArrayList<>();
for (int i : new int[]{1, 2, 3}) {
list.add(i);
}
Using Stream API in Java 8
You can turn the array into a stream, then collect the stream using different collectors: The default collector in Java 8 use ArrayList behind the screen, but you can also impose your preferred implementation.
List<Integer> list1, list2, list3;
list1 = Stream.of(1, 2, 3).collect(Collectors.toList());
list2 = Stream.of(1, 2, 3).collect(Collectors.toCollection(ArrayList::new));
list3 = Stream.of(1, 2, 3).collect(Collectors.toCollection(LinkedList::new));
See also:
Why do we use autoboxing and unboxing in Java?
When to use LinkedList over ArrayList?
Another workaround if you use Apache commons-lang:
int[] numbers = new int[] { 1, 2, 3 };
Arrays.asList(ArrayUtils.toObject(numbers));
Where ArrayUtils.toObject converts int[] to Integer[]
In Java 9 you have the even more elegant solution of using immutable lists via the new convenience factory method List.of:
List<String> immutableList = List.of("one","two","three");
(shamelessly copied from here )
One-liner:
List<Integer> list = Arrays.asList(new Integer[] {1, 2, 3, 4});
If you are targeting Java 8 (or later), you can try this:
int[] numbers = new int[] {1, 2, 3, 4};
List<Integer> integers = Arrays.stream(numbers)
.boxed().collect(Collectors.<Integer>toList());
NOTE:
Pay attention to the Collectors.<Integer>toList(), this generic method helps you to avoid the error "Type mismatch: cannot convert from List<Object> to List<Integer>".
you have to cast in to array
Arrays.asList((Object[]) array)
Using Guava:
Integer[] array = { 1, 2, 3};
List<Integer> list = Lists.newArrayList(sourceArray);
Using Apache Commons Collections:
Integer[] array = { 1, 2, 3};
List<Integer> list = new ArrayList<>(6);
CollectionUtils.addAll(list, array);
I've had the same problem and wrote a generic function that takes an array and returns an ArrayList of the same type with the same contents:
public static <T> ArrayList<T> ArrayToArrayList(T[] array) {
ArrayList<T> list = new ArrayList<T>();
for(T elmt : array) list.add(elmt);
return list;
}
Given Array:
int[] givenArray = {2,2,3,3,4,5};
Converting integer array to Integer List
One way: boxed() -> returns the IntStream
List<Integer> givenIntArray1 = Arrays.stream(givenArray)
.boxed()
.collect(Collectors.toList());
Second Way: map each element of the stream to Integer and then collect
NOTE:
Using mapToObj you can covert each int element into string stream, char stream etc by casing i to (char)i
List<Integer> givenIntArray2 = Arrays.stream(givenArray)
.mapToObj(i->i)
.collect(Collectors.toList());
Converting One array Type to Another Type Example:
List<Character> givenIntArray2 = Arrays.stream(givenArray)
.mapToObj(i->(char)i)
.collect(Collectors.toList());
So it depends on which Java version you are trying-
Java 7
Arrays.asList(1, 2, 3);
OR
final String arr[] = new String[] { "G", "E", "E", "K" };
final List<String> initialList = new ArrayList<String>() {{
add("C");
add("O");
add("D");
add("I");
add("N");
}};
// Elements of the array are appended at the end
Collections.addAll(initialList, arr);
OR
Integer[] arr = new Integer[] { 1, 2, 3 };
Arrays.asList(arr);
In Java 8
int[] num = new int[] {1, 2, 3};
List<Integer> list = Arrays.stream(num)
.boxed().collect(Collectors.<Integer>toList())
Reference - http://www.codingeek.com/java/how-to-convert-array-to-list-in-java/
Can you improve this answer please as this is what I use but im not 100% clear. It works fine but intelliJ added new WeatherStation[0]. Why the 0 ?
public WeatherStation[] removeElementAtIndex(WeatherStation[] array, int index)
{
List<WeatherStation> list = new ArrayList<WeatherStation>(Arrays.asList(array));
list.remove(index);
return list.toArray(new WeatherStation[0]);
}
Use this to convert an Array arr to List.
Arrays.stream(arr).collect(Collectors.toList());
An example of defining a generic method to convert an array to a list:
public <T> List<T> fromArrayToList(T[] a) {
return Arrays.stream(a).collect(Collectors.toList());
}
use two line of code to convert array to list if you use it in integer value
you must use autoboxing type for primitive data type
Integer [] arr={1,2};
List<Integer> listInt=Arrays.asList(arr);
As of Java 8, the following should do
int[] temp = {1, 2, 3, 4, 5};
List<Integer> tempList = Arrays.stream(temp).boxed().collect(Collectors.toList());
If you are trying to optimize for memory, etc., (and don't want to pull in external libraries) it's simpler than you think to implement your own immutable "array view list" – you just need to extend java.util.AbstractList.
class IntArrayViewList extends AbstractList<Integer> {
int[] backingArray;
int size;
IntArrayViewList(int[] backingArray, int size) {
this.backingArray = backingArray;
this.size = size;
}
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int i = 0;
#Override
public boolean hasNext() {
return i < size;
}
#Override
public Integer next() {
return get(i++);
}
};
}
public int size() {
return size;
}
public Integer get(int i) {
return backingArray[i];
}
}
int is a primitive. Primitives can’t accept null and have default value. Hence, to accept null you need to use wrapper class Integer.
Option 1:
int[] nos = { 1, 2, 3, 4, 5 };
Integer[] nosWrapped = Arrays.stream(nos).boxed()   
.toArray(Integer[]::new);
nosWrapped[5] = null // can store null
Option 2:
You can use any data structure that uses the wrapper class Integer
int[] nos = { 1, 2, 3, 4, 5 };
List<Integer> = Arrays.asList(nos)
I started looking at this by trying to reduce the amount of code preparing the input of some test cases. I see a lot of effort around trying to include advanced and new features along with Arrays.asList(), but below the code chosen due simplicity:
//Integer input[]
List<Integer> numbers = Arrays.asList(new Integer[]{1, 2 ,3, 4, 5, 4, 3, 2, 1, 3, 4});
//String input[]
List<String> names = Arrays.asList(new String[]{"Jhon", "Lucas", "Daniel", "Jim", "Sam"});
//String input[]
List<Character> letters = Arrays.asList(new Character[]{'A', 'B', 'K', 'J', 'F'});
Please notice that Anonymous array example will work just with Arrays of Non Primitive Types as the API uses Generics, that's the reason you can see several 2 line examples around, more info here: Why don't Java Generics support primitive types?
For newer JDKs there is another simpler option, the below examples are equivalent to the ones show above:
//Integer
List<Integer> numbers = Arrays.asList(1, 2 ,3, 4, 5, 4, 3, 2, 1, 3, 4);
//String
List<String> names = Arrays.asList("Jhon", "Lucas", "Daniel", "Jim", "Sam");
//Character
List<Character> letters = Arrays.asList('A', 'B', 'K', 'J', 'F');

Categories

Resources