This question already has answers here:
Properly removing an Integer from a List<Integer>
(8 answers)
Closed 9 years ago.
I have the following lists of Integer
whatToRemove = {2, 3, 8};
and another list
lst = {4, 6, 8}
I want to remove all whatToRemove the elements from lst.
I am trying to use lst.remove(whatToRemove.get(i)), but it is trying to remove the index, and not the value.
How can I do that?
List<Integer> whatToRemove = Arrays.asList(2, 3, 8);
List<Integer> lst = new ArrayList<Integer>(Arrays.asList(4, 6, 8));
lst.removeAll(whatToRemove);
Use iterator:
for (Iterator it=lst.iterator(); it.hasNext();) {
if (whatToRemove.contains(it.next())
it.remove();
}
if you are using Java collections to do this, you can simply call removeAll(Collection<T> o) on your first list to remove all occurences.
it would look like lst.removeAll(whatToRemove);
Alternatively you can iterate over all elements easily
for(int num : whatToRemove)
{
lst.remove(num);
}
Both are viable, if you are using arrays, you can still use the enhanced for to iterate. but removing is a different problem.
Link to Javadoc: List
This is because a List has a remove that removes an element by index and a remove that removes by object see:
http://docs.oracle.com/javase/6/docs/api/java/util/List.html#remove(int)
See how there are 2 removes :-(?
Unfortunately as your list contains integers Java thinks that you mean remove( item at) and not remove(object)
Use
Collection lst = [whatever]
lst.remove(whatToRemove.get(i))
...and then the remove should work correctly as Collection only has 1 kind of remove function (the one you want to use)
http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html
Use the removeAll method on List
You can either use removeAll(), which takes an object that implements the Collection interface as the parameter like this:
list.removeAll(collection);
Or you need do some sort of iteration in order to go through all of the values as you want to remove as remove() doesn't take another list as a parameter, only an index or an object:
for(int i=0;i<whatToRemove.size();i++){
lst.remove(whatToRemove.get(i));
}
you can use removeAll(Collection c) method as shown below
lst.removeAll(whatToRemove);
Please check the sample below
List<Integer> whatToRemove = new ArrayList<Integer>();
whatToRemove.add(new Integer(2));
whatToRemove.add(new Integer(3));
whatToRemove.add(new Integer(8));
List<Integer> lst = new ArrayList<Integer>();
lst.add(new Integer(4));
lst.add(new Integer(6));
lst.add(new Integer(8));
lst.removeAll(whatToRemove);
you can refer to below URL for more details on collection and removeAll method
http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html
With the list element you are going to want to remove the index of the objects within the list. For your example it will be integers obviously. To accomplish this you can used a for loop or pull each indexed object out in a manual way.
for loop - example :
for(int i = 0; i < whatToRemove.size(); i++){
whatToRemove.remove(i);
}
manual - example :
whatToRemove.remove(0);
whatToRemove.remove(1);
whatToRemove.remove(2);
This is from what I am understanding from your question that you would like to remove all the elements from your list call "whatToRemove".
Here is a link that may provide some insight into the list parameters Link - Java Object 'List'
Related
I have a HashMap, let's say, with entries {1=1, 3=2, 4=1, 5=1, 6=1} . I'd like to be able to create an array just containing [1,2,1,1,1]. Is that possible?
To give some context, I'm trying to get something I can iterate over using an index, and anything like an array or ArrayList would work (the order of the items does matter).
I tried assigning the values to an array using
for (int j=0; j< frequencies.size(); j++){
for (int i : frequencies.values()) {
arr[j] = i;
}
}
frequencies.values() (frequencies is the name of my HashMap) wasn't of particular use, and I tried both iterating over that (didn't work) and assigning it to Collections wasn't useful. I tried assigning myHashMap.values() to an ArrayList as well, which obviously didn't work.
What would you recommend?
The type of frequencies.values() is a generic Collection, not necessarily an ArrayList. As a result, to convert it to an ArrayList, you must copy it -- fortunately, ArrayList has a constructor that accepts a generic Collection and copies it. As a result, all you have to do is write new ArrayList<>(frequencies.values()).
Is there a way to put all the values of a HashMap in an array?
Since you did specify an array as the target you can do it like this.
Map<Integer,Integer> map = new HashMap<>(Map.of(1,1,3,2,4,1,5,1,6,1));
int[] vals = map.values().stream().mapToInt(Integer::valueOf).toArray();
System.out.println(Arrays.toString(vals));
Prints
[1, 2, 1, 1, 1]
This is a kinda hacky way but it works well for me.... it assumes the values of the numbers from your hashmap are Longs.
Collect the values from your "frequencies" hashmap:
1. Collection<Long> values_from_hashmap = frequencies.values();
Create an array list from the collection of values:
2. ArrayList<Long> listOfValues = new ArrayList<Long>(values_from_hashmap);
Boom your listOfValues array list will contain the values from the orig hashmap
I have a problem with pulling out a value from an Arraylist inside an Arraylist.
I'll just give an example of my problem.
Example:
ArrayList alA = new ArrayList();
ArrayList alB = new ArrayList();
alA.add("1");
alA.add("2");
alA.add("3");
alB.add(alA);
System.out.println(alB.get(0));
This will return [1, 2, 3] as the result.
In my case I only need to print out 3. How do I achieve this?
Just call get on the inner array:
System.out.println(((List) alB.get(0)).get(2));
Note that by using generics, you'll eliminate the need to cast:
List<String> alA = new ArrayList<>();
List<List<String>> alB = new ArrayList<>();
alA.add("1");
alA.add("2");
alA.add("3");
alB.add(alA);
System.out.println(alB.get(0).get(2));
Simply do the following if you don't want to change your other portions of current code
System.out.println(((ArrayList)alB.get(0)).get(2));
System.out.println(alB.get(0)); return alB's 0th index element which is alA. Since you want the element 3, you need to get the 2nd index element of alA, in this case it is alA.get(2);
Combined:
System.out.println(((ArrayList)alB.get(0)).get(2));
What the difference between assigning an arraylist to another and using method addAll between two arraylists?
1 > arrayList = arrayList; //should assign value of later arrayList to the first.
2> arrayList.addAll(arrayList) //add all the data of the later list to first.
the first completely replaces the data in the list ?
the second one for appending data in the list(if it already has any) ???
if i do arrayList.add(arrayList) without assigning any data to the first list, will it insert any data ?
I did the following code for testing and found results that i do'not really know.
secondList.add("1");
secondList.add("2");
firstList = secondList;
Log.i("CHECK","first list = "+ firstList);
firstList.addAll(secondList);
Log.i("CHECK","Firs list add : "+firstList);
firstList.clear();
firstList.addAll(secondList);
Log.i("CHECK","Firs list add 2 : "+firstList);
Result were :
CHECK: first list = [1, 2]
CHECK: Firs list add : [1, 2, 1, 2]
CHECK: Firs list add 2 : []
i was expecting the last log to have result like : [1,2]
as mentioned in docs.oracle.com
addAll- Appends all of the elements in the specified collection to the
end of this list, in the order that they are returned by the specified
collection's Iterator.
and if there's no data in the list ? then what will addAll DO ?
When you do:
firstList = secondList;
What you are saying is actually "to make firstList and secondList refer to the same list". After the line is executed, there will only be one list and two variables both refer to that list.
This is why after you cleared firstList, secondList lost all the elements as well. They refer to the same thing. This has nothing to do with addAll. When you called firstList.addAll(secondList), you are basically adding appending an empty list to another empty list, which results in an empty list.
when you use arrayList = arrayList2; then you are assigning the reference of arrayList2 in first list. That means they are referring to the same list.
and when you use arrayList.addAll(arrayList2) then they are two different list reference.
Now come back to your code (lets denote firstlist as f, second as s)
secondList.add("1"); // f={}, s = {1}
secondList.add("2"); // f={}, s = {1,2}
firstList = secondList; // f= s = {1, 2}
Log.i("CHECK","first list = "+ firstList); // so printing 1,2
firstList.addAll(secondList);// it is actually adding itself.. so f= s = {1,2,1,2}
Log.i("CHECK","Firs list add : "+firstList);
firstList.clear(); // clear boths as s = f
firstList.addAll(secondList); // as boths are blank so overall blank
Log.i("CHECK","Firs list add 2 : "+firstList);
I learned about this in class, Java doesnt really specify when it passes by value or passes by reference, but for the sake of arrayList's, they are pass by reference unless you specifically create new elements. When you say
firstArray = secondArray;
firstArray gets the memory address of the second array, therefore when you cleared the first array, you actually cleared the memory which the second array also shares.
Good luck!
Is there a better alternative to using Arrays.asList as a List bulk initializer? Of concern is that this one is verbose and involves an extraneous class and method.
List<Double> myList = new ArrayList<Double>(Arrays.asList(3.01d, 4.02d, 5.03d));
Edit: This question pertains to a bulk initialization which would usually have more than the three values shown in the example.
If you know that you won't need to add anything to the list later, you can just do
List<Double> myList = Arrays.asList(3.01d, 4.02d, 5.03d);
I'm pretty sure the list returned from Arrays.asList can be modified, but only in that you can change the elements that are there -- you can't add new elements to it.
Use guava,
List<Double> myList = Lists.newArrayList(3.01d, 4.02d, 5.03d));
Doesn't match the question 100%, but adding this answer in case the wanting to instatiate a List was just to be able to immediately do something with the values in it, vs. just instantiating a List for the sake of just doing the instantiation alone.
With Java 8 you can use Stream.of(T... values), then manipulate the steam via the stream API to get the results you would want from the list of values.
For example, to get the max value of a series of values ...
int maxValue = Stream.of(10, 5, 25).max(Integer::compareTo).get();
The above example is also helpful for when you want Math.max(#,#) type functionality, but have more than two arguments to process.
Since java 9 you are able to use List.of factory method:
static <E> List<E> of(E... elements)
Returns an immutable list containing an arbitrary number of elements.
Or use guava:
public static <E> ImmutableList<E> of(E e1, E e2,...)
Returns an immutable list containing the given elements, in order.
Yes, you can do it like this:
List<Double> myList = Arrays.asList(new Double[]{3.01d, 4.02d, 5.03d});
// or
List<Double> myList = Arrays.asList(3.01d, 4.02d, 5.03d);
Another option would be as an anonymous inner class:
List<Double> myList = new ArrayList() {
{
add(3.01d);
add(4.02d);
add(5.03d);
}
};
I have this code:
public static String SelectRandomFromTemplate(String template,int count) {
String[] split = template.split("|");
List<String> list=Arrays.asList(split);
Random r = new Random();
while( list.size() > count ) {
list.remove(r.nextInt(list.size()));
}
return StringUtils.join(list, ", ");
}
I get this:
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): java.lang.UnsupportedOperationException
06-03 15:05:29.614: ERROR/AndroidRuntime(7737): at java.util.AbstractList.remove(AbstractList.java:645)
How would be this the correct way? Java.15
Quite a few problems with your code:
On Arrays.asList returning a fixed-size list
From the API:
Arrays.asList: Returns a fixed-size list backed by the specified array.
You can't add to it; you can't remove from it. You can't structurally modify the List.
Fix
Create a LinkedList, which supports faster remove.
List<String> list = new LinkedList<String>(Arrays.asList(split));
On split taking regex
From the API:
String.split(String regex): Splits this string around matches of the given regular expression.
| is a regex metacharacter; if you want to split on a literal |, you must escape it to \|, which as a Java string literal is "\\|".
Fix:
template.split("\\|")
On better algorithm
Instead of calling remove one at a time with random indices, it's better to generate enough random numbers in the range, and then traversing the List once with a listIterator(), calling remove() at appropriate indices. There are questions on stackoverflow on how to generate random but distinct numbers in a given range.
With this, your algorithm would be O(N).
This one has burned me many times. Arrays.asList creates an unmodifiable list.
From the Javadoc: Returns a fixed-size list backed by the specified array.
Create a new list with the same content:
newList.addAll(Arrays.asList(newArray));
This will create a little extra garbage, but you will be able to mutate it.
Probably because you're working with unmodifiable wrapper.
Change this line:
List<String> list = Arrays.asList(split);
to this line:
List<String> list = new LinkedList<>(Arrays.asList(split));
The list returned by Arrays.asList() might be immutable. Could you try
List<String> list = new ArrayList<>(Arrays.asList(split));
I think that replacing:
List<String> list = Arrays.asList(split);
with
List<String> list = new ArrayList<String>(Arrays.asList(split));
resolves the problem.
Just read the JavaDoc for the asList method:
Returns a {#code List} of the objects
in the specified array. The size of
the {#code List} cannot be modified,
i.e. adding and removing are
unsupported, but the elements can be
set. Setting an element modifies the
underlying array.
This is from Java 6 but it looks like it is the same for the android java.
EDIT
The type of the resulting list is Arrays.ArrayList, which is a private class inside Arrays.class. Practically speaking, it is nothing but a List-view on the array that you've passed with Arrays.asList. With a consequence: if you change the array, the list is changed too. And because an array is not resizeable, remove and add operation must be unsupported.
The issue is you're creating a List using Arrays.asList() method with fixed Length
meaning that
Since the returned List is a fixed-size List, we can’t add/remove elements.
See the below block of code that I am using
This iteration will give an Exception Since it is an iteration list Created by asList() so remove and add are not possible, it is a fixed array
List<String> words = Arrays.asList("pen", "pencil", "sky", "blue", "sky", "dog");
for (String word : words) {
if ("sky".equals(word)) {
words.remove(word);
}
}
This will work fine since we are taking a new ArrayList we can perform modifications while iterating
List<String> words1 = new ArrayList<String>(Arrays.asList("pen", "pencil", "sky", "blue", "sky", "dog"));
for (String word : words) {
if ("sky".equals(word)) {
words.remove(word);
}
}
Arrays.asList() returns a list that doesn't allow operations affecting its size (note that this is not the same as "unmodifiable").
You could do new ArrayList<String>(Arrays.asList(split)); to create a real copy, but seeing what you are trying to do, here is an additional suggestion (you have a O(n^2) algorithm right below that).
You want to remove list.size() - count (lets call this k) random elements from the list. Just pick as many random elements and swap them to the end k positions of the list, then delete that whole range (e.g. using subList() and clear() on that). That would turn it to a lean and mean O(n) algorithm (O(k) is more precise).
Update: As noted below, this algorithm only makes sense if the elements are unordered, e.g. if the List represents a Bag. If, on the other hand, the List has a meaningful order, this algorithm would not preserve it (polygenelubricants' algorithm instead would).
Update 2: So in retrospect, a better (linear, maintaining order, but with O(n) random numbers) algorithm would be something like this:
LinkedList<String> elements = ...; //to avoid the slow ArrayList.remove()
int k = elements.size() - count; //elements to select/delete
int remaining = elements.size(); //elements remaining to be iterated
for (Iterator i = elements.iterator(); k > 0 && i.hasNext(); remaining--) {
i.next();
if (random.nextInt(remaining) < k) {
//or (random.nextDouble() < (double)k/remaining)
i.remove();
k--;
}
}
This UnsupportedOperationException comes when you try to perform some operation on collection where its not allowed and in your case, When you call Arrays.asList it does not return a java.util.ArrayList. It returns a java.util.Arrays$ArrayList which is an immutable list. You cannot add to it and you cannot remove from it.
I've got another solution for that problem:
List<String> list = Arrays.asList(split);
List<String> newList = new ArrayList<>(list);
work on newList ;)
Replace
List<String> list=Arrays.asList(split);
to
List<String> list = New ArrayList<>();
list.addAll(Arrays.asList(split));
or
List<String> list = new ArrayList<>(Arrays.asList(split));
or
List<String> list = new ArrayList<String>(Arrays.asList(split));
or (Better for Remove elements)
List<String> list = new LinkedList<>(Arrays.asList(split));
Yes, on Arrays.asList, returning a fixed-size list.
Other than using a linked list, simply use addAll method list.
Example:
String idList = "123,222,333,444";
List<String> parentRecepeIdList = new ArrayList<String>();
parentRecepeIdList.addAll(Arrays.asList(idList.split(",")));
parentRecepeIdList.add("555");
You can't remove, nor can you add to a fixed-size-list of Arrays.
But you can create your sublist from that list.
list = list.subList(0, list.size() - (list.size() - count));
public static String SelectRandomFromTemplate(String template, int count) {
String[] split = template.split("\\|");
List<String> list = Arrays.asList(split);
Random r = new Random();
while( list.size() > count ) {
list = list.subList(0, list.size() - (list.size() - count));
}
return StringUtils.join(list, ", ");
}
*Other way is
ArrayList<String> al = new ArrayList<String>(Arrays.asList(template));
this will create ArrayList which is not fixed size like Arrays.asList
Arrays.asList() uses fixed size array internally.
You can't dynamically add or remove from thisArrays.asList()
Use this
Arraylist<String> narraylist=new ArrayList(Arrays.asList());
In narraylist you can easily add or remove items.
Arraylist narraylist=Arrays.asList(); // Returns immutable arraylist
To make it mutable solution would be:
Arraylist narraylist=new ArrayList(Arrays.asList());
Following is snippet of code from Arrays
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/**
* #serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
so what happens is that when asList method is called then it returns list of its own private static class version which does not override add funcion from AbstractList to store element in array. So by default add method in abstract list throws exception.
So it is not regular array list.
Creating a new list and populating valid values in new list worked for me.
Code throwing error -
List<String> list = new ArrayList<>();
for (String s: list) {
if(s is null or blank) {
list.remove(s);
}
}
desiredObject.setValue(list);
After fix -
List<String> list = new ArrayList<>();
List<String> newList= new ArrayList<>();
for (String s: list) {
if(s is null or blank) {
continue;
}
newList.add(s);
}
desiredObject.setValue(newList);