Tôi có một ArrayList<String>
, và tôi muốn loại bỏ các chuỗi lặp đi lặp lại từ nó. Tôi có thể làm cái này như thế nào?
Tôi có một ArrayList<String>
, và tôi muốn loại bỏ các chuỗi lặp đi lặp lại từ nó. Tôi có thể làm cái này như thế nào?
Câu trả lời:
Nếu bạn không muốn trùng lặp trong một Collection
, bạn nên xem xét lý do tại sao bạn sử dụng một Collection
bản sao cho phép trùng lặp. Cách dễ nhất để loại bỏ các phần tử lặp lại là thêm nội dung vào một Set
(sẽ không cho phép trùng lặp) và sau đó thêm phần Set
sau vào ArrayList
:
Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);
Tất nhiên, điều này phá hủy thứ tự của các yếu tố trong ArrayList
.
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; }
List
và Set
(thay vì các loại triển khai ArrayList
và HashSet
như trong ví dụ của bạn).
new HashSet(al)
thay vì khởi tạo nó để trống và gọi addAll
.
Object
giá trị của tôi có một vài giá trị nếu hai trong số chúng lặp lại, tôi coi chúng là trùng lặp (các giá trị khác có thể khác nhau) và sử dụng Set
?
Mặc dù chuyển đổi ArrayList
một HashSet
cách hiệu quả loại bỏ bản sao, nếu bạn cần phải giữ gìn trật tự chèn, tôi thà khuyên bạn nên sử dụng phiên bản này
// list is some List of Strings
Set<String> s = new LinkedHashSet<>(list);
Sau đó, nếu bạn cần lấy lại List
tham chiếu, bạn có thể sử dụng lại hàm tạo chuyển đổi.
Trong Java 8:
List<String> deduped = list.stream().distinct().collect(Collectors.toList());
Xin lưu ý rằng hợp đồng hashCode-Equals cho các thành viên trong danh sách nên được tôn trọng để bộ lọc hoạt động chính xác.
addAll
đến new TreeSet<String>(String.CASE_INSENSITIVE_ORDER)
. Phần tử đầu tiên được thêm sẽ vẫn còn trong tập hợp vì vậy nếu danh sách của bạn chứa "Dog" và "dog" (theo thứ tự đó) thì TreeSet
sẽ chứa "Dog". Nếu thứ tự phải được bảo tồn thì trước khi dòng trong câu trả lời đặt list.replaceAll(String::toUpperCase);
.
Giả sử chúng ta có một danh sách String
như:
List<String> strList = new ArrayList<>(5);
// insert up to five items to list.
Sau đó, chúng ta có thể loại bỏ các yếu tố trùng lặp theo nhiều cách.
List<String> deDupStringList = new ArrayList<>(new HashSet<>(strList));
Lưu ý: Nếu chúng tôi muốn duy trì thứ tự chèn thì chúng tôi cần sử dụngLinkedHashSet
thay choHashSet
List<String> deDupStringList2 = Lists.newArrayList(Sets.newHashSet(strList));
List<String> deDupStringList3 = strList.stream().distinct().collect(Collectors.toList());
Lưu ý: Trong trường hợp chúng tôi muốn thu thập kết quả trong việc thực hiện danh sách cụ thể, ví dụ: LinkedList
sau đó chúng tôi có thể sửa đổi ví dụ trên như:
List<String> deDupStringList3 = strList.stream().distinct()
.collect(Collectors.toCollection(LinkedList::new));
Chúng tôi cũng có thể sử dụng parallelStream
trong đoạn mã trên nhưng nó có thể không mang lại lợi ích hiệu suất mong đợi. Kiểm tra câu hỏi này để biết thêm.
parallel streams
sẽ luôn mang lại hiệu quả tốt hơn. Nhưng đó là một huyền thoại. Sau này tôi mới biết rằng có một số kịch bản nhất định trong đó các luồng song song nên được sử dụng. Trong kịch bản này, các luồng song song sẽ không cho hiệu năng tốt hơn. và có các luồng song song có thể không cho kết quả mong muốn một số trường hợp. List<String> deDupStringList3 = stringList.stream().map(String::toLowerCase).distinct().collect(Collectors.toList());
nên là giải pháp phù hợp trong trường hợp này
Nếu bạn không muốn trùng lặp, hãy sử dụng Set thay vì a List
. Để chuyển đổi a List
thành a, Set
bạn có thể sử dụng đoạn mã sau:
// list is some List of Strings
Set<String> s = new HashSet<String>(list);
Nếu thực sự cần thiết, bạn có thể sử dụng cùng một cấu trúc để chuyển đổi Set
trở lại thành một List
.
Set
không thể được sử dụng ở đây.
Bạn cũng có thể làm theo cách này và giữ trật tự:
// delete duplicates (if any) from 'myArrayList'
myArrayList = new ArrayList<String>(new LinkedHashSet<String>(myArrayList));
Các luồng Java 8 cung cấp một cách rất đơn giản để loại bỏ các phần tử trùng lặp khỏi danh sách. Sử dụng phương pháp riêng biệt. Nếu chúng tôi có một danh sách các thành phố và chúng tôi muốn xóa các bản sao khỏi danh sách đó, nó có thể được thực hiện trong một dòng -
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());
Đây là một cách không ảnh hưởng đến thứ tự danh sách của bạn:
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 là danh sách ban đầu và l2 là danh sách không có các mục lặp lại (Đảm bảo YourClass có phương thức bằng theo những gì bạn muốn đại diện cho sự bình đẳng)
ArrayList<T>
nên được sử dụng thay vì ArrayList
) 2) Có thể tránh việc tạo iterator rõ ràng bằng cách sử dụng a for (T current : l1) { ... }
. Ngay cả khi bạn muốn sử dụng một Iterator
cách rõ ràng, iterador
là sai chính tả.
Có thể xóa các bản sao khỏi danh sách mảng mà không cần sử dụng Hashset hoặc thêm một danh sách mảng .
Hãy thử mã này ..
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);
Đầu ra là
Duplicates List [ABC, ABC, ABCD, ABCD, ABCE]
Distinct List [ABC, ABCD, ABCE]
ImmutableSet.copyOf(lst).toList()
.
indexOf
lặp lại việc lst
sử dụng một vòng lặp for.
Ngoài ra còn có ImmutableSet
từ Guava như một tùy chọn ( đây là tài liệu):
ImmutableSet.copyOf(list);
ImmutableSet.asList()
phương thức, trả về một ImmutableList
, nếu bạn cần nó trở lại như một List
.
điều này có thể giải quyết vấn đề:
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;
}
Có lẽ hơi quá mức, nhưng tôi thích loại vấn đề bị cô lập này. :)
Mã này sử dụng Bộ tạm thời (để kiểm tra tính duy nhất) nhưng loại bỏ các yếu tố trực tiếp trong danh sách ban đầu. Vì việc loại bỏ phần tử bên trong một ArrayList có thể tạo ra một lượng lớn sao chép mảng, nên việc loại bỏ (int) -method được tránh.
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);
}
}
Trong khi chúng tôi đang ở đó, đây là phiên bản dành cho LinkedList (đẹp hơn rất nhiều!):
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();
}
}
}
Sử dụng giao diện đánh dấu để trình bày một giải pháp hợp nhất cho Danh sách:
public static <T> void removeDuplicates(List<T> list) {
if (list instanceof RandomAccess) {
// use first version here
} else {
// use other version here
}
}
EDIT: Tôi đoán các công cụ thuốc generic không thực sự bổ sung bất kỳ giá trị nào ở đây .. Oh tốt. :)
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);
}
Nếu bạn sẵn sàng sử dụng thư viện của bên thứ ba, bạn có thể sử dụng phương thức này distinct()
trong Bộ sưu tập Eclipse (trước đây là Bộ sưu tập GS).
ListIterable<Integer> integers = FastList.newListWith(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
FastList.newListWith(1, 3, 2),
integers.distinct());
Ưu điểm của việc sử dụng distinct()
thay vì chuyển đổi thành Tập hợp rồi quay lại Danh sách là distinct()
giữ nguyên thứ tự của Danh sách gốc, giữ lại lần xuất hiện đầu tiên của mỗi thành phần. Nó được thực hiện bằng cách sử dụng cả Tập hợp và Danh sách.
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;
Nếu bạn không thể chuyển đổi Danh sách ban đầu của mình thành loại Bộ sưu tập Eclipse, bạn có thể sử dụng ListAd CHƯƠNG để có cùng API.
MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();
Lưu ý: Tôi là người đi làm cho Bộ sưu tập Eclipse.
Ba dòng mã này có thể loại bỏ phần tử trùng lặp khỏi ArrayList hoặc bất kỳ bộ sưu tập nào.
List<Entity> entities = repository.findByUserId(userId);
Set<Entity> s = new LinkedHashSet<Entity>(entities);
entities.clear();
entities.addAll(s);
Khi bạn điền vào ArrayList, hãy sử dụng một điều kiện cho mỗi phần tử. Ví dụ:
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 + " ");
}
Chúng ta sẽ nhận được một mảng {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Nếu bạn muốn duy trì Đơn hàng của mình thì tốt nhất nên sử dụng LinkedHashset . Bởi vì nếu bạn muốn chuyển Danh sách này cho một Truy vấn Chèn bằng cách Lặp lại nó, thứ tự sẽ được giữ nguyên.
Thử cái này
LinkedHashSet link=new LinkedHashSet();
List listOfValues=new ArrayList();
listOfValues.add(link);
Chuyển đổi này sẽ rất hữu ích khi bạn muốn trả về Danh sách nhưng không phải là Bộ.
Mã số:
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);
Lưu ý: Chắc chắn, sẽ có bộ nhớ trên đầu.
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();
LinkedHashSet sẽ thực hiện các mẹo.
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());
// đầu ra: 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]
Điều này được sử dụng cho danh sách Đối tượng tùy chỉnh của bạn
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;
}
bạn có thể sử dụng vòng lặp lồng nhau theo sau:
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);
}
Đây là mã của tôi mà không sử dụng bất kỳ cấu trúc dữ liệu nào khác như set hoặc 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--;
}
}
}
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);
Nếu bạn muốn loại bỏ trùng lặp khỏi ArrayList có nghĩa là tìm logic bên dưới,
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;
}