This question already has answers here:
How do I remove repeated elements from ArrayList?
(40 answers)
Closed 9 years ago.
I have a very lengthy ArrayList comprised of objects some of them however, are undoubtedly duplicates. What is the best way of finding and removing these duplicates. Note: I have written a boolean-returning compareObjects() method.
Example
List<Item> result = new ArrayList<Item>();
Set<String> titles = new HashSet<String>();
for( Item item : originalList ) {
if( titles.add( item.getTitle() )) {
result.add( item );
}
}
Reference
Set
Java Data Structures
You mentioned writing a compareObjects method. Actually, you should override the equals method to return true when two objects are equal.
Having said that, I would just return a new list that contains unique elements from the original:
ArrayList<T> original = ...
List<T> uniques = new ArrayList<T>();
for (T element : original) {
if (!uniques.contains(element)) {
uniques.add(element);
}
}
This only works if you override equals. See this question for more information.
Hashset will remove duplicates. Example:
Set< String > uniqueItems = new HashSet< String >();
uniqueItems.add("a");
uniqueItems.add("a");
uniqueItems.add("b");
uniqueItems.add("c");
The set "uniqueItems" will contain the following : a, b, c
Related
This question already has answers here:
How can I initialize an ArrayList with all zeroes in Java?
(5 answers)
Creating a list with repeating element
(5 answers)
Create an array with n copies of the same value/object?
(7 answers)
Closed 1 year ago.
Is there a way to fast initialize a new ArrayList object with X same objects?
Here is an example code:
private List<String> initStringArrayList(int size, String s) {
List<String> list = new ArrayList<>(size);
while (size-- > 0) {
list.add(s);
}
return list;
}
I want to have the same result, but much faster for large "size" values.
Of course, I could use this code:
private List<String> initStringArrayList(int size, String s) {
String[] array = new String[size];
Arrays.fill(array, s);
return new ArrayList<>(Arrays.asList(array));
}
But the constructor of ArrayList<>() would copy the full array instead of using it internal. That would not be acceptable.
Is there another way to do so? I need an ArrayList as result, not just a list. And it should be of any type, not just for strings.
Thank you for any answer!
Use Collections.nCopies, and copy it into an ArrayList:
private <T> List<T> initStringArrayList(int size, T s) {
return new ArrayList<>(Collections.nCopies(size, s));
}
This assumes that you really do want a mutable List at the end. If you can make do with an immutable list with the item size times, Collections.nCopies(size, s) by itself would work: it is memory-efficient, fast to allocate etc.
This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 2 years ago.
I have a String List.On a satisfied Condition ,I need to group strings and remove those before iterating.
For example;
List<String> test = new ArrayList();
List<String> newLst = new ArrayList();
test.add("A1");
test.add("A2");
test.add("A3");
test.add("A1B1");
test.add("C1");
for(String s: test){
if(s.startsWith("A"){
newLst.add(s);
test.remove(s);
}
}
Once A1 reaches the loop,collect related string in new list and remove it from existing.
Getting Concurrent Modification exception.Kindly help to solve this.
Output:
newLst: A1,A2,A3
test : A1B1,C1
newLst : A1B1
test:C1
newLst : C1
You could use an explicit Iterator to iterate over the List, and use that Iterator's remove() method inside the loop (instead of List's remove()), but it would be simpler to remove from test all the elements added to newLst after the loop:
for(String s: test){
if(s.startsWith("A"){
newLst.add(s);
}
}
test.removeAll(newLst);
You can filter out elements starting with A using stream:
List<String> result = test.stream()
.filter(line -> line.startsWith("A"))
.collect(Collectors.toList());
result.forEach(System.out::println); //This is for printing elements
Why you are getting ConcurrentModificationException ?
That's because you are trying to modify the collection while iterating over it's items. The only safe way to modify your collection during iteration Iterator.remove(); The same applies for Iterator.add() (Whether you delete or add an item it counts as a modification).
JDK < 8 SOLUTION
List<String> sourceList = new ArrayList();
List<String> destList = new ArrayList();
sourceList.add("A1");
sourceList.add("A2");
sourceList.add("A3");
sourceList.add("A1B1");
sourceList.add("C1");
Iterator<String> iterator = sourceList.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
if(s.startsWith("A"){
destList.add(s);
iterator.remove(s);
}
}
JDK > 8 SOLUTION
List<String> destList = sourceList.stream()
.filter(item -> item.startsWith("A"))
.collect(Collectors.toList());
Note that Java streams use Spliterator which quite different than an Iterator.
A stream source is described by an abstraction called Spliterator. As its name suggests, Spliterator combines two behaviors: accessing the elements of the source (iterating), and possibly decomposing the input source for parallel execution (splitting).
For further details , i advise you to check this interesting post about how streams works under the hood
This question already has answers here:
Is there a way to access an iteration-counter in Java's for-each loop?
(16 answers)
Closed 3 years ago.
here Is Code there any way to get Index of the object from the list by calling a method in the list.
for example something like this:
class A{
String a="";
String b="";
}
List<A> alist= new ArrayList();
for (A a : alist) {
a.getIndexInList();
}
Why not use indexOf? If I recall correctly it is a built-in function of list.
List<A> alist= new ArrayList<>();
for (A a : alist) {
int index = alist.indexOf(a);
}
Only the list can give you the index. Unless the object in the array knows it's in an array it can't give you it's index.
There is no builtin solution, you can use external counter:
List<A> alist= new ArrayList();
int counter = 0;
for (A a : alist) {
// logic
counter++;
}
You could also create a map with indices as keys, something like:
IntStream.range(0, alist.size()).mapToObj(Integer::valueOf)
.collect(Collectors.toMap(
Function.identity(),
alist::get
));
but alist needs to be effectively final.
This question already has answers here:
How to lowercase every element of a collection efficiently?
(11 answers)
Closed 6 years ago.
I'm having trouble figuring out how to apply a math operation to each item of an ArrayList. The ArrayList will be user inputted so there's no telling how many items would be within it. Is there a method that might aid in doing this?
Use ListIterator -> https://docs.oracle.com/javase/7/docs/api/java
/util/ListIterator.html
Unlike plain Iterator, ListIterator will allow you to store newly computed value back to the list
ArrayList<Integer> source = ...
ListIterator<Integer> iter = source.listIterator();
while( iter.hasNext() )
{
Integer value = iter.next();
Integer newValue = Integer.valueOf( value.intValue() * 2 );
iter.set(newValue);
}
as #puhlen says, in java 8, use stream and lambda expression
List liste = new ArrayList<>();
liste.stream().forEach(o->{
//apply your math on o
});
stream provides you many other functionnalities to filter, order, collect... use it if you're on java8
or as #neil-locketz says in java before 8 use a foreach loop
List<type> liste = new ArrayList<>();
for(type o : liste){
//math on object o here
}
This question already has answers here:
Remove duplicates from ArrayLists
(14 answers)
Closed 9 years ago.
In my program I have an array list containing product objects in it. I want to remove duplicated product objects from it. Is there any efficient way other than looping over each element and compare them.
just add all element into set. it wont allow duplicate values
List<Product> list=new ArrayList<>();
Set<Product> set=new HashSet<>();
set.addAll(list);
Just pass your list Collection to Hashset constructor and Get it back.
Then that one liner will be,
list = new ArrayList<E>(new HashSet<E>(list));
You can just put element into Set. Set keep unique values only.
List<String> list=new ArrayList<>();
Set<String> set=new HashSet<>();
set.addAll(list); // now you have unique value set
If you want to final result as unique value List just you need to get this Set as List
List<String> uniqueValList=new ArrayList<>(set);
You can use a Set but you will loose the original order of your list.
What you can do to keep the order is:
Set<E> copied = new HashSet<>();
List<E> res = new ArrayList<>();
for(E e : originalList) {
if(!copied.contains(e)) {
res.add(e);
}
copied.add(e);
}
Use Set instead of list it will remove duplicates
Try to use Set instead of List. Set wont allow duplicate values.
The advice above to use Set is good - but if you need to keep the order just use a LinkedHashSet http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashSet.html
List<String> list = ...
Set<String> set = new LinkedHashSet<>(list);
list.clear();
list.addAll(set);
That will preserve order and remove all duplicates.
The result will be case sensitive though in the case of strings.