Best way to get unique list without changing the Order - java

I have a list of string or list of integers of 20,000 items
Now it contains duplicates...However i don't want to disturb the order of the item.
We can easily convert a list to Set for unique Set unique = new HashSet(list);
However the above breaks the sequential order of the items.
What would be the best approach for this?
Thanks.

You should use java.util.LinkedHashSet to get unique elements without changing the order:
Set<String> uniqueSet = new LinkedHashSet<>(list);
One other way is to use distinct():
list.stream().distinct().collect(Collectors.toList())
But distinct() uses LinkedHashSet internally. There is no need for unnecessary procedure.
So best way is using the LinkedHashSet constructor:
LinkedHashSet(Collection c) Constructs a new linked hash
set with the same elements as the specified collection.

You can try stream distinct
yourList.stream().distinct().collect(Collectors.toList());
Update1:
As I know, this is the best solution.
list.contains(element) will do 2 loop processes. One for iterate the element and add it to new list, one for check element is contained -> 0(n*n)
new LinkedHashSet() will created a new LinkedHashSet, and a new Arraylist output -> issue about memory. And the performance, i think it is equals with stream distinct
Update2: we must ensure that the output is a List, not a Set
As I know, stream distinct use HashSet internally. It is an more efficient memory implementation than LinkedHashSet (which is hash table and linked list implementation of the set interface) in our case.
Detail here
If you apply LinkedHashSet, the source code will something like below, so we have 1 ArrayList and 1 LinkedHashSet.
output = new ArrayList(new LinkedHashSet(yourList));
I did a small benchmark with 1k for-loop.
int size = 1000000;
Random rand = new Random((int) (System.currentTimeMillis() / 1000));
List<Integer> yourList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
yourList.add(rand.nextInt(10000));
}
// test1: LinkedHashSet --> 35ms
new ArrayList<Integer>(new LinkedHashSet<Integer>(yourList));
// test2: Stream distinct --> 30ms
yourList.stream().distinct().collect(Collectors.toList());

If you don't want to break the order, then Iterate the list and make a new list as below.
ArrayList<Integer> newList = new ArrayList<Integer>();
for (Integer element : list) {
if (!newList.contains(element)) {
newList.add(element);
}
}

Try the bellow code
public static void main(String[] args) {
String list[] = {"9","1","1","9","2","7","2"};
List<String> unique = new ArrayList<>();
for(int i=0; i<list.length; i++) {
int count = unique.size();
if(count==0) {
unique.add(list[i]);
}else {
boolean available = false;
for(int j=0; j<count; j++) {
if(unique.get(j).equals(list[i])) {
available = true;
break;
}
}
if(!available) {
unique.add(list[i]);
}
}
}
//checking latest 'unique' value
for(int i=0; i<unique.size(); i++) {
System.out.println(unique.get(i));
}
}
It will return 9 1 2 7, but I haven't tried up to 20,000 collection lists, hopefully there are no performance issues

If you are trying to eliminate duplicates, you can use LinkedHashSet it will maintain the order.
if String
Set<String> dedupSet = new LinkedHashSet<>();
if Integer
Set<Integer> dedupSet = new LinkedHashSet<>();

Related

Get differences between two arrayList but compare them in uppercase

I have two arrayList and I need to compare them, get the values that are uniques and build a new array with them, problem is some of the values are the same but in uppercase so they shouldn't show as unique value. This is my code alredy, works but is to slow
for (i = 0; i < parsedLocal.size(); i++) {
for (j = 0; j < parsedRemote.size(); j++) {
if (parsedLocal[i].toUpperCase().equals(parsedRemote[j].toUpperCase())){
parsedLocal.remove(parsedLocal[i])
}
}
}
Then I found this solution that is faster but doesn't compare uppercases or lowercases, any idea on how to do that with that method or similar?
parsedLocal.removeAll(parsedRemote);
The following groovy code should compute the difference (note that the returned collection will contain upper-case values):
parsedLocal*.toUpperCase() - parsedRemote*.toUpperCase()
But you can also use a stream-based computation. This has a slightly higher space complexity, but should have linear time complexity:
Set<String> set1 = parsedLocal.stream()
.map{it.toUpperCase()}
.collect(Collectors.toSet());
List<String> retained = parsedRemote.stream()
.filter{!set1.contains(it.toUpperCase())}
.collect(Collectors.toList());
Using removeIf can be easy in java 8 as follows:
List<String> parsedLocal = new ArrayList();
parsedLocal.add("aa");
parsedLocal.add("bb");
List<String> parsedRemote = new ArrayList();
parsedRemote.add("AA");
List<String> tmpList = new ArrayList<>(parsedLocal);
for (String s : parsedRemote) {
tmpList.removeIf((t) -> t.equalsIgnoreCase(s));
}
System.out.println(tmpList);
And the output:
[bb]

Remove duplicates elements from ArrayList which compose of Collection [duplicate]

I have an ArrayList<String>, and I want to remove repeated strings from it. How can I do this?
If you don't want duplicates in a Collection, you should consider why you're using a Collection that allows duplicates. The easiest way to remove repeated elements is to add the contents to a Set (which will not allow duplicates) and then add the Set back to the ArrayList:
Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);
Of course, this destroys the ordering of the elements in the ArrayList.
Although converting the ArrayList to a HashSet effectively removes duplicates, if you need to preserve insertion order, I'd rather suggest you to use this variant
// list is some List of Strings
Set<String> s = new LinkedHashSet<>(list);
Then, if you need to get back a List reference, you can use again the conversion constructor.
In Java 8:
List<String> deduped = list.stream().distinct().collect(Collectors.toList());
Please note that the hashCode-equals contract for list members should be respected for the filtering to work properly.
Suppose we have a list of String like:
List<String> strList = new ArrayList<>(5);
// insert up to five items to list.
Then we can remove duplicate elements in multiple ways.
Prior to Java 8
List<String> deDupStringList = new ArrayList<>(new HashSet<>(strList));
Note: If we want to maintain the insertion order then we need to use LinkedHashSet in place of HashSet
Using Guava
List<String> deDupStringList2 = Lists.newArrayList(Sets.newHashSet(strList));
Using Java 8
List<String> deDupStringList3 = strList.stream().distinct().collect(Collectors.toList());
Note: In case we want to collect the result in a specific list implementation e.g. LinkedList then we can modify the above example as:
List<String> deDupStringList3 = strList.stream().distinct()
.collect(Collectors.toCollection(LinkedList::new));
We can use parallelStream also in the above code but it may not give expected performace benefits. Check this question for more.
If you don't want duplicates, use a Set instead of a List. To convert a List to a Set you can use the following code:
// list is some List of Strings
Set<String> s = new HashSet<String>(list);
If really necessary you can use the same construction to convert a Set back into a List.
Java 8 streams provide a very simple way to remove duplicate elements from a list. Using the distinct method.
If we have a list of cities and we want to remove duplicates from that list it can be done in a single line -
List<String> cityList = new ArrayList<>();
cityList.add("Delhi");
cityList.add("Mumbai");
cityList.add("Bangalore");
cityList.add("Chennai");
cityList.add("Kolkata");
cityList.add("Mumbai");
cityList = cityList.stream().distinct().collect(Collectors.toList());
How to remove duplicate elements from an arraylist
You can also do it this way, and preserve order:
// delete duplicates (if any) from 'myArrayList'
myArrayList = new ArrayList<String>(new LinkedHashSet<String>(myArrayList));
Here's a way that doesn't affect your list ordering:
ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();
Iterator iterator = l1.iterator();
while (iterator.hasNext()) {
YourClass o = (YourClass) iterator.next();
if(!l2.contains(o)) l2.add(o);
}
l1 is the original list, and l2 is the list without repeated items
(Make sure YourClass has the equals method according to what you want to stand for equality)
this can solve the problem:
private List<SomeClass> clearListFromDuplicateFirstName(List<SomeClass> list1) {
Map<String, SomeClass> cleanMap = new LinkedHashMap<String, SomeClass>();
for (int i = 0; i < list1.size(); i++) {
cleanMap.put(list1.get(i).getFirstName(), list1.get(i));
}
List<SomeClass> list = new ArrayList<SomeClass>(cleanMap.values());
return list;
}
It is possible to remove duplicates from arraylist without using HashSet or one more arraylist.
Try this code..
ArrayList<String> lst = new ArrayList<String>();
lst.add("ABC");
lst.add("ABC");
lst.add("ABCD");
lst.add("ABCD");
lst.add("ABCE");
System.out.println("Duplicates List "+lst);
Object[] st = lst.toArray();
for (Object s : st) {
if (lst.indexOf(s) != lst.lastIndexOf(s)) {
lst.remove(lst.lastIndexOf(s));
}
}
System.out.println("Distinct List "+lst);
Output is
Duplicates List [ABC, ABC, ABCD, ABCD, ABCE]
Distinct List [ABC, ABCD, ABCE]
There is also ImmutableSet from Guava as an option (here is the documentation):
ImmutableSet.copyOf(list);
Probably a bit overkill, but I enjoy this kind of isolated problem. :)
This code uses a temporary Set (for the uniqueness check) but removes elements directly inside the original list. Since element removal inside an ArrayList can induce a huge amount of array copying, the remove(int)-method is avoided.
public static <T> void removeDuplicates(ArrayList<T> list) {
int size = list.size();
int out = 0;
{
final Set<T> encountered = new HashSet<T>();
for (int in = 0; in < size; in++) {
final T t = list.get(in);
final boolean first = encountered.add(t);
if (first) {
list.set(out++, t);
}
}
}
while (out < size) {
list.remove(--size);
}
}
While we're at it, here's a version for LinkedList (a lot nicer!):
public static <T> void removeDuplicates(LinkedList<T> list) {
final Set<T> encountered = new HashSet<T>();
for (Iterator<T> iter = list.iterator(); iter.hasNext(); ) {
final T t = iter.next();
final boolean first = encountered.add(t);
if (!first) {
iter.remove();
}
}
}
Use the marker interface to present a unified solution for List:
public static <T> void removeDuplicates(List<T> list) {
if (list instanceof RandomAccess) {
// use first version here
} else {
// use other version here
}
}
EDIT: I guess the generics-stuff doesn't really add any value here.. Oh well. :)
public static void main(String[] args){
ArrayList<Object> al = new ArrayList<Object>();
al.add("abc");
al.add('a');
al.add('b');
al.add('a');
al.add("abc");
al.add(10.3);
al.add('c');
al.add(10);
al.add("abc");
al.add(10);
System.out.println("Before Duplicate Remove:"+al);
for(int i=0;i<al.size();i++){
for(int j=i+1;j<al.size();j++){
if(al.get(i).equals(al.get(j))){
al.remove(j);
j--;
}
}
}
System.out.println("After Removing duplicate:"+al);
}
If you're willing to use a third-party library, you can use the method distinct() in Eclipse Collections (formerly GS Collections).
ListIterable<Integer> integers = FastList.newListWith(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
FastList.newListWith(1, 3, 2),
integers.distinct());
The advantage of using distinct() instead of converting to a Set and then back to a List is that distinct() preserves the order of the original List, retaining the first occurrence of each element. It's implemented by using both a Set and a List.
MutableSet<T> seenSoFar = UnifiedSet.newSet();
int size = list.size();
for (int i = 0; i < size; i++)
{
T item = list.get(i);
if (seenSoFar.add(item))
{
targetCollection.add(item);
}
}
return targetCollection;
If you cannot convert your original List into an Eclipse Collections type, you can use ListAdapter to get the same API.
MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();
Note: I am a committer for Eclipse Collections.
If you are using model type List< T>/ArrayList< T> . Hope,it's help you.
Here is my code without using any other data structure like set or hashmap
for (int i = 0; i < Models.size(); i++){
for (int j = i + 1; j < Models.size(); j++) {
if (Models.get(i).getName().equals(Models.get(j).getName())) {
Models.remove(j);
j--;
}
}
}
If you want to preserve your Order then it is best to use LinkedHashSet.
Because if you want to pass this List to an Insert Query by Iterating it, the order would be preserved.
Try this
LinkedHashSet link=new LinkedHashSet();
List listOfValues=new ArrayList();
listOfValues.add(link);
This conversion will be very helpful when you want to return a List but not a Set.
This three lines of code can remove the duplicated element from ArrayList or any collection.
List<Entity> entities = repository.findByUserId(userId);
Set<Entity> s = new LinkedHashSet<Entity>(entities);
entities.clear();
entities.addAll(s);
for(int a=0;a<myArray.size();a++){
for(int b=a+1;b<myArray.size();b++){
if(myArray.get(a).equalsIgnoreCase(myArray.get(b))){
myArray.remove(b);
dups++;
b--;
}
}
}
When you are filling the ArrayList, use a condition for each element. For example:
ArrayList< Integer > al = new ArrayList< Integer >();
// fill 1
for ( int i = 0; i <= 5; i++ )
if ( !al.contains( i ) )
al.add( i );
// fill 2
for (int i = 0; i <= 10; i++ )
if ( !al.contains( i ) )
al.add( i );
for( Integer i: al )
{
System.out.print( i + " ");
}
We will get an array {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Code:
List<String> duplicatList = new ArrayList<String>();
duplicatList = Arrays.asList("AA","BB","CC","DD","DD","EE","AA","FF");
//above AA and DD are duplicate
Set<String> uniqueList = new HashSet<String>(duplicatList);
duplicatList = new ArrayList<String>(uniqueList); //let GC will doing free memory
System.out.println("Removed Duplicate : "+duplicatList);
Note: Definitely, there will be memory overhead.
ArrayList<String> city=new ArrayList<String>();
city.add("rajkot");
city.add("gondal");
city.add("rajkot");
city.add("gova");
city.add("baroda");
city.add("morbi");
city.add("gova");
HashSet<String> hashSet = new HashSet<String>();
hashSet.addAll(city);
city.clear();
city.addAll(hashSet);
Toast.makeText(getActivity(),"" + city.toString(),Toast.LENGTH_SHORT).show();
you can use nested loop in follow :
ArrayList<Class1> l1 = new ArrayList<Class1>();
ArrayList<Class1> l2 = new ArrayList<Class1>();
Iterator iterator1 = l1.iterator();
boolean repeated = false;
while (iterator1.hasNext())
{
Class1 c1 = (Class1) iterator1.next();
for (Class1 _c: l2) {
if(_c.getId() == c1.getId())
repeated = true;
}
if(!repeated)
l2.add(c1);
}
LinkedHashSet will do the trick.
String[] arr2 = {"5","1","2","3","3","4","1","2"};
Set<String> set = new LinkedHashSet<String>(Arrays.asList(arr2));
for(String s1 : set)
System.out.println(s1);
System.out.println( "------------------------" );
String[] arr3 = set.toArray(new String[0]);
for(int i = 0; i < arr3.length; i++)
System.out.println(arr3[i].toString());
//output: 5,1,2,3,4
List<String> result = new ArrayList<String>();
Set<String> set = new LinkedHashSet<String>();
String s = "ravi is a good!boy. But ravi is very nasty fellow.";
StringTokenizer st = new StringTokenizer(s, " ,. ,!");
while (st.hasMoreTokens()) {
result.add(st.nextToken());
}
System.out.println(result);
set.addAll(result);
result.clear();
result.addAll(set);
System.out.println(result);
output:
[ravi, is, a, good, boy, But, ravi, is, very, nasty, fellow]
[ravi, is, a, good, boy, But, very, nasty, fellow]
This is used for your Custom Objects list
public List<Contact> removeDuplicates(List<Contact> list) {
// Set set1 = new LinkedHashSet(list);
Set set = new TreeSet(new Comparator() {
#Override
public int compare(Object o1, Object o2) {
if (((Contact) o1).getId().equalsIgnoreCase(((Contact) o2).getId()) /*&&
((Contact)o1).getName().equalsIgnoreCase(((Contact)o2).getName())*/) {
return 0;
}
return 1;
}
});
set.addAll(list);
final List newList = new ArrayList(set);
return newList;
}
As said before, you should use a class implementing the Set interface instead of List to be sure of the unicity of elements. If you have to keep the order of elements, the SortedSet interface can then be used; the TreeSet class implements that interface.
import java.util.*;
class RemoveDupFrmString
{
public static void main(String[] args)
{
String s="appsc";
Set<Character> unique = new LinkedHashSet<Character> ();
for(char c : s.toCharArray()) {
System.out.println(unique.add(c));
}
for(char dis:unique){
System.out.println(dis);
}
}
}
public Set<Object> findDuplicates(List<Object> list) {
Set<Object> items = new HashSet<Object>();
Set<Object> duplicates = new HashSet<Object>();
for (Object item : list) {
if (items.contains(item)) {
duplicates.add(item);
} else {
items.add(item);
}
}
return duplicates;
}
ArrayList<String> list = new ArrayList<String>();
HashSet<String> unique = new LinkedHashSet<String>();
HashSet<String> dup = new LinkedHashSet<String>();
boolean b = false;
list.add("Hello");
list.add("Hello");
list.add("how");
list.add("are");
list.add("u");
list.add("u");
for(Iterator iterator= list.iterator();iterator.hasNext();)
{
String value = (String)iterator.next();
System.out.println(value);
if(b==unique.add(value))
dup.add(value);
else
unique.add(value);
}
System.out.println(unique);
System.out.println(dup);
If you want to remove duplicates from ArrayList means find the below logic,
public static Object[] removeDuplicate(Object[] inputArray)
{
long startTime = System.nanoTime();
int totalSize = inputArray.length;
Object[] resultArray = new Object[totalSize];
int newSize = 0;
for(int i=0; i<totalSize; i++)
{
Object value = inputArray[i];
if(value == null)
{
continue;
}
for(int j=i+1; j<totalSize; j++)
{
if(value.equals(inputArray[j]))
{
inputArray[j] = null;
}
}
resultArray[newSize++] = value;
}
long endTime = System.nanoTime()-startTime;
System.out.println("Total Time-B:"+endTime);
return resultArray;
}

Removing Duplicate Values from ArrayList

I have one Arraylist of String and I have added Some Duplicate Value in that. and i just wanna remove that Duplicate value So how to remove it.
Here Example I got one Idea.
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
System.out.println("List"+list);
for (int i = 1; i < list.size(); i++) {
String a1 = list.get(i);
String a2 = list.get(i-1);
if (a1.equals(a2)) {
list.remove(a1);
}
}
System.out.println("List after short"+list);
But is there any Sufficient way remove that Duplicate form list. with out using For loop ?
And ya i can do it by using HashSet or some other way but using array list only.
would like to have your suggestion for that. thank you for your answer in advance.
You can create a LinkedHashSet from the list. The LinkedHashSet will contain each element only once, and in the same order as the List. Then create a new List from this LinkedHashSet. So effectively, it's a one-liner:
list = new ArrayList<String>(new LinkedHashSet<String>(list))
Any approach that involves List#contains or List#remove will probably decrease the asymptotic running time from O(n) (as in the above example) to O(n^2).
EDIT For the requirement mentioned in the comment: If you want to remove duplicate elements, but consider the Strings as equal ignoring the case, then you could do something like this:
Set<String> toRetain = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
toRetain.addAll(list);
Set<String> set = new LinkedHashSet<String>(list);
set.retainAll(new LinkedHashSet<String>(toRetain));
list = new ArrayList<String>(set);
It will have a running time of O(n*logn), which is still better than many other options. Note that this looks a little bit more complicated than it might have to be: I assumed that the order of the elements in the list may not be changed. If the order of the elements in the list does not matter, you can simply do
Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
set.addAll(list);
list = new ArrayList<String>(set);
if you want to use only arraylist then I am worried there is no better way which will create a huge performance benefit. But by only using arraylist i would check before adding into the list like following
void addToList(String s){
if(!yourList.contains(s))
yourList.add(s);
}
In this cases using a Set is suitable.
You can make use of Google Guava utilities, as shown below
list = ImmutableSet.copyOf(list).asList();
This is probably the most efficient way of eliminating the duplicates from the list and interestingly, it preserves the iteration order as well.
UPDATE
But, in case, you don't want to involve Guava then duplicates can be removed as shown below.
ArrayList<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
System.out.println("List"+list);
HashSet hs = new HashSet();
hs.addAll(list);
list.clear();
list.addAll(hs);
But, of course, this will destroys the iteration order of the elements in the ArrayList.
Shishir
Java 8 stream function
You could use the distinct function like above to get the distinct elements of the list,
stringList.stream().distinct();
From the documentation,
Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.
Another way, if you do not wish to use the equals method is by using the collect function like this,
stringList.stream()
.collect(Collectors.toCollection(() ->
new TreeSet<String>((p1, p2) -> p1.compareTo(p2))
));
From the documentation,
Performs a mutable reduction operation on the elements of this stream using a Collector.
Hope that helps.
Simple function for removing duplicates from list
private void removeDuplicates(List<?> list)
{
int count = list.size();
for (int i = 0; i < count; i++)
{
for (int j = i + 1; j < count; j++)
{
if (list.get(i).equals(list.get(j)))
{
list.remove(j--);
count--;
}
}
}
}
Example:
Input: [1, 2, 2, 3, 1, 3, 3, 2, 3, 1, 2, 3, 3, 4, 4, 4, 1]
Output: [1, 2, 3, 4]
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
HashSet<String> hs=new HashSet<>(list);
System.out.println("=========With Duplicate Element========");
System.out.println(list);
System.out.println("=========Removed Duplicate Element========");
System.out.println(hs);
I don't think the list = new ArrayList<String>(new LinkedHashSet<String>(list)) is not the best way , since we are using the LinkedHashset(We could use directly LinkedHashset instead of ArrayList),
Solution:
import java.util.ArrayList;
public class Arrays extends ArrayList{
#Override
public boolean add(Object e) {
if(!contains(e)){
return super.add(e);
}else{
return false;
}
}
public static void main(String[] args) {
Arrays element=new Arrays();
element.add(1);
element.add(2);
element.add(2);
element.add(3);
System.out.println(element);
}
}
Output:
[1, 2, 3]
Here I am extending the ArrayList , as I am using the it with some changes by overriding the add method.
public List<Contact> removeDuplicates(List<Contact> list) {
// Set set1 = new LinkedHashSet(list);
Set set = new TreeSet(new Comparator() {
#Override
public int compare(Object o1, Object o2) {
if(((Contact)o1).getId().equalsIgnoreCase(((Contact)2).getId()) ) {
return 0;
}
return 1;
}
});
set.addAll(list);
final List newList = new ArrayList(set);
return newList;
}
This will be the best way
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
Set<String> set=new HashSet<>(list);
It is better to use HastSet
1-a) A HashSet holds a set of objects, but in a way that it allows you to easily and quickly determine whether an object is already in the set or not. It does so by internally managing an array and storing the object using an index which is calculated from the hashcode of the object. Take a look here
1-b) HashSet is an unordered collection containing unique elements. It has the standard collection operations Add, Remove, Contains, but since it uses a hash-based implementation, these operation are O(1). (As opposed to List for example, which is O(n) for Contains and Remove.) HashSet also provides standard set operations such as union, intersection, and symmetric difference.Take a look here
2) There are different implementations of Sets. Some make insertion and lookup operations super fast by hashing elements. However that means that the order in which the elements were added is lost. Other implementations preserve the added order at the cost of slower running times.
The HashSet class in C# goes for the first approach, thus not preserving the order of elements. It is much faster than a regular List. Some basic benchmarks showed that HashSet is decently faster when dealing with primary types (int, double, bool, etc.). It is a lot faster when working with class objects. So that point is that HashSet is fast.
The only catch of HashSet is that there is no access by indices. To access elements you can either use an enumerator or use the built-in function to convert the HashSet into a List and iterate through that.Take a look here
Without a loop, No! Since ArrayList is indexed by order rather than by key, you can not found the target element without iterate the whole list.
A good practice of programming is to choose proper data structure to suit your scenario. So if Set suits your scenario the most, the discussion of implementing it with List and trying to find the fastest way of using an improper data structure makes no sense.
public static void main(String[] args) {
#SuppressWarnings("serial")
List<Object> lst = new ArrayList<Object>() {
#Override
public boolean add(Object e) {
if(!contains(e))
return super.add(e);
else
return false;
}
};
lst.add("ABC");
lst.add("ABC");
lst.add("ABCD");
lst.add("ABCD");
lst.add("ABCE");
System.out.println(lst);
}
This is the better way
list = list.stream().distinct().collect(Collectors.toList());
This could be one of the solutions using Java8 Stream API. Hope this helps.
public void removeDuplicates() {
ArrayList<Object> al = new ArrayList<Object>();
al.add("java");
al.add('a');
al.add('b');
al.add('a');
al.add("java");
al.add(10.3);
al.add('c');
al.add(14);
al.add("java");
al.add(12);
System.out.println("Before Remove Duplicate elements:" + al);
for (int i = 0; i < al.size(); i++) {
for (int j = i + 1; j < al.size(); j++) {
if (al.get(i).equals(al.get(j))) {
al.remove(j);
j--;
}
}
}
System.out.println("After Removing duplicate elements:" + al);
}
Before Remove Duplicate elements:
[java, a, b, a, java, 10.3, c, 14, java, 12]
After Removing duplicate elements:
[java, a, b, 10.3, c, 14, 12]
Using java 8:
public static <T> List<T> removeDuplicates(List<T> list) {
return list.stream().collect(Collectors.toSet()).stream().collect(Collectors.toList());
}
In case you just need to remove the duplicates using only ArrayList, no other Collection classes, then:-
//list is the original arraylist containing the duplicates as well
List<String> uniqueList = new ArrayList<String>();
for(int i=0;i<list.size();i++) {
if(!uniqueList.contains(list.get(i)))
uniqueList.add(list.get(i));
}
Hope this helps!
private static void removeDuplicates(List<Integer> list)
{
Collections.sort(list);
int count = list.size();
for (int i = 0; i < count; i++)
{
if(i+1<count && list.get(i)==list.get(i+1)){
list.remove(i);
i--;
count--;
}
}
}
public static List<String> removeDuplicateElements(List<String> array){
List<String> temp = new ArrayList<String>();
List<Integer> count = new ArrayList<Integer>();
for (int i=0; i<array.size()-2; i++){
for (int j=i+1;j<array.size()-1;j++)
{
if (array.get(i).compareTo(array.get(j))==0) {
count.add(i);
int kk = i;
}
}
}
for (int i = count.size()+1;i>0;i--) {
array.remove(i);
}
return array;
}
}

How to move data from multiple Arraylist to multiple Arrays (in Java)

I have 3 arraylist each have size = 3 and 3 arrays also have length = 3 of each. I want to copy data from arraylists to arrays in following way but using any loop (i.e for OR for each).
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
I have done it manually one by one without using any loop, but code appears to be massive because in future I'm sure that number of my arraylists and arrays will increase up to 15.
I want to copy the data from arraylists to arrays as shown in the image but using the loops not manually one by one?
How about this?
List<Integer> arraylist0 = Arrays.asList(2,4,3);
List<Integer> arraylist1 = Arrays.asList(2,5,7);
List<Integer> arraylist2 = Arrays.asList(6,3,7);
List<List<Integer>> arraylistList = Arrays.asList(arraylist0, arraylist1, arraylist2);
int size = 3;
int[] myArray0 = new int[size];
int[] myArray1 = new int[size];
int[] myArray2 = new int[size];
int[][] myBigArray = new int[][] {myArray0, myArray1, myArray2};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
myBigArray[i][j] = arraylistList.get(j).get(i);
}
}
To explain, since we want to be able to work with an arbitrary size (3, 15, or more), we are dealing with 2-dimensional data.
We are also dealing with array and List, which are slightly different in their use.
The input to your problem is List<Integer>, and so we make a List<List<Integer>> in order to deal with all the input data easily.
Similarly, the output will be arrays, so we make a 2-dimensional array (int[][]) in order to write the data easily.
Then it's simply a matter of iterating over the data in 2 nested for loops. Notice that this line reverses the order of i and j in order to splice the data the way you intend.
myBigArray[i][j] = arraylistList.get(j).get(i);
And then you can print your answer like this:
System.out.println(Arrays.toString(myArray0));
System.out.println(Arrays.toString(myArray1));
System.out.println(Arrays.toString(myArray2));
You need to have two additional structures:
int[][] destination = new int [][] {myArray1, myArray2,myArray3 }
List<Integer>[] source;
source = new List<Integer>[] {arraylist1,arraylist2,arraylist3}
myArray1[1] = arraylist1.get(1);
myArray1[2] = arraylist2.get(1);
myArray1[3] = arraylist3.get(1);
for (int i=0;i<destination.length;i++) {
for (int j=0;j<source.length;j++) {
destination[i][j] = source[j].get(i);
}
}
If you cannot find a ready made API or function for this, I would suggest trivializing the conversion from List to Array using the List.toArray() method and focus on converting/transforming the given set of lists to a another bunch of lists which contain the desired output. Following is a code sample which I would think achieves this. It does assume the input lists are NOT of fixed/same sizes. Assuming this would only make the logic easier.
On return of this function, all you need to do is to iterate over the TreeMap and convert the values to arrays using List.toArray().
public static TreeMap<Integer, List<Integer>> transorm(
List<Integer>... lists) {
// Return a blank TreeMap if not input. TreeMap explanation below.
if (lists == null || lists.length == 0)
return new TreeMap<>();
// Get Iterators for the input lists
List<Iterator<Integer>> iterators = new ArrayList<>();
for (List<Integer> list : lists) {
iterators.add(list.iterator());
}
// Initialize Return. We return a TreeMap, where the key indicates which
// position's integer values are present in the list which is the value
// of this key. Converting the lists to arrays is trivial using the
// List.toArray() method.
TreeMap<Integer, List<Integer>> transformedLists = new TreeMap<>();
// Variable maintaining the position for which values are being
// collected. See below.
int currPosition = 0;
// Variable which keeps track of the index of the iterator currently
// driving the iteration and the driving iterator.
int driverItrIndex = 0;
Iterator<Integer> driverItr = lists[driverItrIndex].iterator();
// Actual code that does the transformation.
while (driverItrIndex < iterators.size()) {
// Move to next driving iterator
if (!driverItr.hasNext()) {
driverItrIndex++;
driverItr = iterators.get(driverItrIndex);
continue;
}
// Construct Transformed List
ArrayList<Integer> transformedList = new ArrayList<>();
for (Iterator<Integer> iterator : iterators) {
if (iterator.hasNext()) {
transformedList.add(iterator.next());
}
}
// Add to return
transformedLists.put(currPosition, transformedList);
}
// Return Value
return transformedLists;
}

Get objects' index in a Java List

I have a list of strings in my (Android) Java program, and I need to get the index of an object in the list. The problem is, I can only find documentation on how to find the first and last index of an object. What if I have 3 or more of the same object in my list? How can I find every index?
Thanks!
You need to do a brute force search:
static <T> List<Integer> indexesOf(List<T> source, T target)
{
final List<Integer> indexes = new ArrayList<Integer>();
for (int i = 0; i < source.size(); i++) {
if (source.get(i).equals(target)) { indexes.add(i); }
}
return indexes;
}
Note that this is not necessarily the most efficient approach. Depending on the context and the types/sizes of lists, you might need to do some serious optimizations. The point is, if you need every index (and know nothing about the structure of the list contents), then you need to do a deathmarch through every item for at best O(n) cost.
Depending on the type of the underlying list, get(i) may be O(1) (ArrayList) or O(n) (LinkedList), so this COULD blow up to a O(n2) implementation. You could copy to an ArrayList, or you could walk the LinkedList incrementing an index counter manually.
If documentation is not helping me in my logic in this situation i would have gone for a raw approach for Traversing the list in a loop and saving the index where i found a match
ArrayList<String> obj = new ArrayList<String>();
obj.add("Test Data"): // fill the list with your data
String dataToFind = "Hello";
ArrayList<Integer> intArray = new ArrayList<Integer>();
for(int i = 0 ; i<obj.size() ; i++)
{
if(obj.get(i).equals(dataToFind)) intArray.add(i);
}
now intArray would have contained all the index of matched element in the list
An alternative brute force approach that will also find all null indexes:
static List<Integer> indexesOf(List<?> list, Object target) {
final List<Integer> indexes = new ArrayList<Integer>();
int offset = 0;
for (int i = list.indexOf(target); i != -1; i = list.indexOf(target)) {
indexes.add(i + offset);
list = list.subList(i + 1, list.size());
offset += i + 1;
}
return indexes;
}

Categories