Tôi có một Danh sách kiểu Integer, vd:
[1, 1, 2, 3, 3, 3]
Tôi muốn một phương thức trả về tất cả các bản sao, ví dụ:
[1, 3]
Cách tốt nhất để làm việc này là gì?
Tôi có một Danh sách kiểu Integer, vd:
[1, 1, 2, 3, 3, 3]
Tôi muốn một phương thức trả về tất cả các bản sao, ví dụ:
[1, 3]
Cách tốt nhất để làm việc này là gì?
Câu trả lời:
Phương pháp add
của Set
lợi nhuận một boolean liệu một giá trị đã tồn tại (true nếu nó không tồn tại, false nếu nó đã tồn tại, xem Set tài liệu ).
Vì vậy, chỉ cần lặp qua tất cả các giá trị:
public Set<Integer> findDuplicates(List<Integer> listContainingDuplicates)
{
final Set<Integer> setToReturn = new HashSet<>();
final Set<Integer> set1 = new HashSet<>();
for (Integer yourInt : listContainingDuplicates)
{
if (!set1.add(yourInt))
{
setToReturn.add(yourInt);
}
}
return setToReturn;
}
for (Integer yourInt
, để tránh đấm bốc và bỏ hộp không cần thiết, đặc biệt vì đầu vào của bạn đã chứa Integer
s.
HashSet
bạn cũng phải xem xét hệ số tải, ví dụ: khi bạn chỉ định công suất ban đầu là 100
, vì bạn muốn thêm số phần tử đó, nó sẽ được làm tròn thành lũy thừa 2 ( 128
), hàm ý rằng với hệ số tải mặc định là 0.75f
, ngưỡng thay đổi kích thước sẽ là 96
, do đó sẽ có thay đổi kích thước trước khi bạn thêm 100
các yếu tố. Rất may, thay đổi kích thước không còn đắt nữa. Với các JRE cập nhật, thay đổi kích thước sẽ không được thử lại nữa, các phần tử chỉ được phân phối giữa hai vị trí kết quả có thể có của chúng dựa trên bit có liên quan.
Tôi cần một giải pháp cho điều này là tốt. Tôi đã sử dụng giải pháp của leifg và làm cho nó chung chung.
private <T> Set<T> findDuplicates(Collection<T> collection) {
Set<T> duplicates = new LinkedHashSet<>();
Set<T> uniques = new HashSet<>();
for(T t : collection) {
if(!uniques.add(t)) {
duplicates.add(t);
}
}
return duplicates;
}
Tôi đã lấy giải pháp của John Strickler và làm lại nó để sử dụng API luồng được giới thiệu trong JDK8:
private <T> Set<T> findDuplicates(Collection<T> collection) {
Set<T> uniques = new HashSet<>();
return collection.stream()
.filter(e -> !uniques.add(e))
.collect(Collectors.toSet());
}
distinct()
phương thức dựng sẵn cũng có trạng thái. Không thể nghĩ ra một hoạt động riêng biệt hiệu quả (O (n)) không trạng thái.
Đây là một giải pháp sử dụng Luồng với Java 8
// lets assume the original list is filled with {1,1,2,3,6,3,8,7}
List<String> original = new ArrayList<>();
List<String> result = new ArrayList<>();
Bạn chỉ cần xem tần số của đối tượng này nhiều hơn một lần trong danh sách của bạn. Sau đó gọi .distotype () để chỉ có các phần tử duy nhất trong kết quả của bạn
result = original.stream()
.filter(e -> Collections.frequency(original, e) > 1)
.distinct()
.collect(Collectors.toList());
// returns {1,3}
// returns only numbers which occur more than once
result = original.stream()
.filter(e -> Collections.frequency(original, e) == 1)
.collect(Collectors.toList());
// returns {2,6,8,7}
// returns numbers which occur only once
result = original.stream()
.distinct()
.collect(Collectors.toList());
// returns {1,2,3,6,8,7}
// returns the list without duplicates
Collections::frequency
là O (n). Nó cần phải đi qua toàn bộ bộ sưu tập để tìm tần số của một mặt hàng. Và chúng tôi gọi điều này một lần cho mỗi mục trong bộ sưu tập, điều này tạo nên những đoạn trích này O(n^2)
. Bạn sẽ nhận thấy sự khác biệt trong bất kỳ bộ sưu tập nào hơn một số yếu tố. Tôi sẽ không bao giờ sử dụng điều này trong mã thực tế.
giải pháp cơ sở java 8:
List duplicates =
list.stream().collect(Collectors.groupingBy(Function.identity()))
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
int[] nums = new int[] {1, 1, 2, 3, 3, 3};
Arrays.sort(nums);
for (int i = 0; i < nums.length-1; i++) {
if (nums[i] == nums[i+1]) {
System.out.println("duplicate item "+nums[i+1]+" at Location"+(i+1) );
}
}
Rõ ràng bạn có thể làm bất cứ điều gì bạn muốn với chúng (ví dụ: đặt vào Set để nhận danh sách giá trị trùng lặp duy nhất) thay vì in ... Điều này cũng có lợi ích là ghi lại vị trí của các mục trùng lặp.
Sử dụng ổi trên Java 8
private Set<Integer> findDuplicates(List<Integer> input) {
// Linked* preserves insertion order so the returned Sets iteration order is somewhat like the original list
LinkedHashMultiset<Integer> duplicates = LinkedHashMultiset.create(input);
// Remove all entries with a count of 1
duplicates.entrySet().removeIf(entry -> entry.getCount() == 1);
return duplicates.elementSet();
}
Điều này cũng hoạt động:
public static Set<Integer> findDuplicates(List<Integer> input) {
List<Integer> copy = new ArrayList<Integer>(input);
for (Integer value : new HashSet<Integer>(input)) {
copy.remove(value);
}
return new HashSet<Integer>(copy);
}
Bạn có thể sử dụng một cái gì đó như thế này:
List<Integer> newList = new ArrayList<Integer>();
for(int i : yourOldList)
{
yourOldList.remove(i);
if(yourOldList.contains(i) && !newList.contains(i)) newList.add(i);
}
int
như loại biến ở đây. Điều đó có nghĩa là với mỗi lần lặp duy nhất, một Integer được bỏ hộp một lần và một int được đóng hộp bốn lần!
Lambas có thể là một giải pháp
Integer[] nums = new Integer[] {1, 1, 2, 3, 3, 3};
List<Integer> list = Arrays.asList(nums);
List<Integer> dps = list.stream().distinct().filter(entry -> Collections.frequency(list, entry) > 1).collect(Collectors.toList());
Nếu bạn sử dụng Bộ sưu tập Eclipse , điều này sẽ hoạt động:
MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectByOccurrences(i -> i > 1).toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);
Cập nhật: Kể từ Bộ sưu tập Eclipse 9.2, bây giờ bạn có thể sử dụngselectDuplicates
MutableList<Integer> list = Lists.mutable.with(1, 1, 2, 3, 3, 3);
Set<Integer> dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(Sets.mutable.with(1, 3), dupes);
Bạn cũng có thể sử dụng các bộ sưu tập nguyên thủy để thực hiện điều này:
IntList list = IntLists.mutable.with(1, 1, 2, 3, 3, 3);
IntSet dupes = list.toBag().selectDuplicates().toSet();
Assert.assertEquals(IntSets.mutable.with(1, 3), dupes);
Ghi chú: Tôi là người đi làm cho Bộ sưu tập Eclipse.
public class practicese {
public static void main(String[] args) {
List<Integer> listOf = new ArrayList<Integer>();
listOf.add(3);
listOf.add(1);
listOf.add(2);
listOf.add(3);
listOf.add(3);
listOf.add(2);
listOf.add(1);
List<Integer> tempList = new ArrayList<Integer>();
for(Integer obj:listOf){
if(!tempList.contains(obj)){
tempList.add(obj);
}
}
System.out.println(tempList);
}
}
Tương tự như một số câu trả lời ở đây, nhưng nếu bạn muốn tìm các bản sao dựa trên một số thuộc tính:
public static <T, R> Set<R> findDuplicates(Collection<? extends T> collection, Function<? super T, ? extends R> mapper) {
Set<R> uniques = new HashSet<>();
return collection.stream()
.map(mapper)
.filter(e -> !uniques.add(e))
.collect(toSet());
}
tạo a Map<Integer,Integer>
, lặp lại danh sách, nếu một yếu tố có trong bản đồ, hãy tăng giá trị của nó, nếu không hãy thêm nó vào bản đồ với key = 1
lặp lại bản đồ và thêm vào danh sách tất cả các yếu tố có khóa> = 2
public static void main(String[] args) {
List<Integer> list = new LinkedList<Integer>();
list.add(1);
list.add(1);
list.add(1);
list.add(2);
list.add(3);
list.add(3);
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
for (Integer x : list) {
Integer val = map.get(x);
if (val == null) {
map.put(x,1);
} else {
map.remove(x);
map.put(x,val+1);
}
}
List<Integer> result = new LinkedList<Integer>();
for (Entry<Integer, Integer> entry : map.entrySet()) {
if (entry.getValue() > 1) {
result.add(entry.getKey());
}
}
for (Integer x : result) {
System.out.println(x);
}
}
Phiên bản nhỏ gọn của câu trả lời hàng đầu, cũng được thêm kiểm tra trống và kích thước cài đặt sẵn:
public static final <T> Set<T> findDuplicates(final List<T> listWhichMayHaveDuplicates) {
final Set<T> duplicates = new HashSet<>();
final int listSize = listWhichMayHaveDuplicates.size();
if (listSize > 0) {
final Set<T> tempSet = new HashSet<>(listSize);
for (final T element : listWhichMayHaveDuplicates) {
if (!tempSet.add(element)) {
duplicates.add(element);
}
}
}
return duplicates;
}
tempSet
với listSize
khi cần thiết. Đây là một tối ưu hóa nhỏ nhưng tôi thích nó.
Tôi lấy câu trả lời của Sebastian và thêm keyExtractor vào nó -
private <U, T> Set<T> findDuplicates(Collection<T> collection, Function<? super T,? extends U> keyExtractor) {
Map<U, T> uniques = new HashMap<>(); // maps unique keys to corresponding values
return collection.stream()
.filter(e -> uniques.put(keyExtractor.apply(e), e) != null)
.collect(Collectors.toSet());
}
Một thay thế an toàn chủ đề là đây:
/**
* Returns all duplicates that are in the list as a new {@link Set} thread-safe.
* <p>
* Usually the Set will contain only the last duplicate, however the decision
* what elements are equal depends on the implementation of the {@link List}. An
* exotic implementation of {@link List} might decide two elements are "equal",
* in this case multiple duplicates might be returned.
*
* @param <X> The type of element to compare.
* @param list The list that contains the elements, never <code>null</code>.
* @return A set of all duplicates in the list. Returns only the last duplicate.
*/
public <X extends Object> Set<X> findDuplicates(List<X> list) {
Set<X> dups = new LinkedHashSet<>(list.size());
synchronized (list) {
for (X x : list) {
if (list.indexOf(x) != list.lastIndexOf(x)) {
dups.add(x);
}
}
}
return dups;
}
Hãy thử điều này để tìm các mục trùng lặp trong danh sách:
ArrayList<String> arrayList1 = new ArrayList<String>();
arrayList1.add("A");
arrayList1.add("A");
arrayList1.add("B");
arrayList1.add("B");
arrayList1.add("B");
arrayList1.add("C");
for (int x=0; x< arrayList1.size(); x++)
{
System.out.println("arrayList1 :"+arrayList1.get(x));
}
Set s=new TreeSet();
s.addAll(arrayList1);
Iterator it=s.iterator();
while (it.hasNext())
{
System.out.println("Set :"+(String)it.next());
}
Điều này sẽ làm việc để sắp xếp và chưa sắp xếp.
public void testFindDuplicates() {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(1);
list.add(2);
list.add(3);
list.add(3);
list.add(3);
Set<Integer> result = new HashSet<Integer>();
int currentIndex = 0;
for (Integer i : list) {
if (!result.contains(i) && list.subList(currentIndex + 1, list.size()).contains(i)) {
result.add(i);
}
currentIndex++;
}
assertEquals(2, result.size());
assertTrue(result.contains(1));
assertTrue(result.contains(3));
}
Đây là một vấn đề mà các kỹ thuật chức năng tỏa sáng. Ví dụ, giải pháp F # sau đây rõ ràng hơn và ít bị lỗi hơn so với giải pháp Java bắt buộc tốt nhất (và tôi làm việc hàng ngày với cả Java và F #).
[1;1;2;3;3;3]
|> Seq.countBy id
|> Seq.choose (fun (key,count) -> if count > 1 then Some(key) else None)
Tất nhiên, câu hỏi này là về Java. Vì vậy, đề nghị của tôi là chấp nhận một thư viện mang các tính năng chức năng cho Java. Ví dụ, nó có thể được giải quyết bằng thư viện của riêng tôi như sau (và có một số cái khác ngoài đó cũng đáng xem):
Seq.of(1,1,2,3,3,3)
.groupBy(new Func1<Integer,Integer>() {
public Integer call(Integer key) {
return key;
}
}).filter(new Predicate<Grouping<Integer,Integer>>() {
public Boolean call(Grouping<Integer, Integer> grouping) {
return grouping.getGrouping().count() > 1;
}
}).map(new Func1<Grouping<Integer,Integer>,Integer>() {
public Integer call(Grouping<Integer, Integer> grouping) {
return grouping.getKey();
}
});
public class DuplicatesWithOutCollection {
public static void main(String[] args) {
int[] arr = new int[] { 2, 3, 4, 6, 6, 8, 10, 10, 10, 11, 12, 12 };
boolean flag = false;
int k = 1;
while (k == 1) {
arr = removeDuplicate(arr);
flag = checkDuplicate(arr, flag);
if (flag) {
k = 1;
} else {
k = 0;
}
}
}
private static boolean checkDuplicate(int[] arr, boolean flag) {
int i = 0;
while (i < arr.length - 1) {
if (arr[i] == arr[i + 1]) {
flag = true;
} else {
flag = false;
}
i++;
}
return flag;
}
private static int[] removeDuplicate(int[] arr) {
int i = 0, j = 0;
int[] temp = new int[arr.length];
while (i < arr.length - 1) {
if (arr[i] == arr[i + 1]) {
temp[j] = arr[i + 1];
i = i + 2;
} else {
temp[j] = arr[i];
i = i + 1;
if (i == arr.length - 1) {
temp[j + 1] = arr[i + 1];
break;
}
}
j++;
}
System.out.println();
return temp;
}
}
import java.util.Scanner;
public class OnlyDuplicates {
public static void main(String[] args) {
System.out.print(" Enter a set of 10 numbers: ");
int[] numbers = new int[10];
Scanner input = new Scanner(System.in);
for (int i = 0; i < numbers.length; i++) {
numbers[i] = input.nextInt();
}
numbers = onlyDuplicates(numbers);
System.out.print(" The numbers are: ");
for (int i = 0; i < numbers.length; i++) {
System.out.print(numbers[i] + "");
}
}
public static int[] onlyDuplicates(int[] list) {
boolean flag = true;
int[] array = new int[0];
array = add2Array(array, list[0]);
for (int i = 0; i < list.length; i++) {
for (int j = 0; j < array.length; j++) {
if (list[i] == array[j]) {
flag = false;
break;
}
}
if (flag) {
array = add2Array(array, list[i]);
}
flag = true;
}
return array;
}
// Copy numbers1 to numbers2
// If the length of numbers2 is less then numbers2, return false
public static boolean copyArray(int[] source, int[] dest) {
if (source.length > dest.length) {
return false;
}
for (int i = 0; i < source.length; i++) {
dest[i] = source[i];
}
return true;
}
// Increase array size by one and add integer to the end of the array
public static int[] add2Array(int[] source, int data) {
int[] dest = new int[source.length + 1];
copyArray(source, dest);
dest[source.length] = data;
return dest;
}
}
Đây sẽ là một phương pháp tốt để tìm các giá trị trùng lặp mà không cần sử dụng Set.
public static <T> List<T> findDuplicates(List<T> list){
List<T> nonDistinctElements = new ArrayList<>();
for(T s : list)
if(list.indexOf(s) != list.lastIndexOf(s))
if(!nonDistinctElements.contains(s))
nonDistinctElements.add(s);
return nonDistinctElements;
}
Và giả sử, bạn muốn một phương thức trả về cho bạn một danh sách riêng, tức là nếu bạn vượt qua một danh sách nơi các phần tử xuất hiện nhiều lần, bạn sẽ nhận được một danh sách có các phần tử riêng biệt.
public static <T> void distinctList(List<T> list){
List<T> nonDistinctElements = new ArrayList<>();
for(T s : list)
if(list.indexOf(s) != list.lastIndexOf(s))
nonDistinctElements.add(s);
for(T nonDistinctElement : nonDistinctElements)
if(list.indexOf(nonDistinctElement) != list.lastIndexOf(nonDistinctElement))
list.remove(nonDistinctElement);
}
Và phiên bản sử dụng commons-collections
CollectionUtils.getCardinalityMap
phương thức:
final List<Integer> values = Arrays.asList(1, 1, 2, 3, 3, 3);
final Map<Integer, Integer> cardinalityMap = CollectionUtils.getCardinalityMap(values);
System.out.println(cardinalityMap
.entrySet()
.stream().filter(e -> e.getValue() > 1)
.map(e -> e.getKey())
.collect(Collectors.toList()));
`` `
Làm thế nào về mã này -
public static void main(String[] args) {
//Lets say we have a elements in array
int[] a = {13,65,13,67,88,65,88,23,65,88,92};
List<Integer> ls1 = new ArrayList<>();
List<Integer> ls2 = new ArrayList<>();
Set<Integer> ls3 = new TreeSet<>();
//Adding each element of the array in the list
for(int i=0;i<a.length;i++) {
{
ls1.add(a[i]);
}
}
//Iterating each element in the arrary
for (Integer eachInt : ls1) {
//If the list2 contains the iterating element, then add that into set<> (as this would be a duplicate element)
if(ls2.contains(eachInt)) {
ls3.add(eachInt);
}
else {ls2.add(eachInt);}
}
System.out.println("Elements in array or ls1"+ls1);
System.out.println("Duplicate Elements in Set ls3"+ls3);
}
chỉ trong trường hợp cho những người cũng muốn bao gồm cả trùng lặp và không trùng lặp. về cơ bản câu trả lời giống với câu trả lời đúng nhưng thay vì trả về từ nếu không phải là phần bạn trả lại phần khác
sử dụng mã này (thay đổi loại bạn cần)
public Set<String> findDup(List<String> Duplicates){
Set<String> returning = new HashSet<>();
Set<String> nonreturning = new HashSet<>();
Set<String> setup = new HashSet<>();
for(String i:Duplicates){
if(!setup.add( i )){
returning.add( i );
}else{
nonreturning.add( i );
}
}
Toast.makeText( context,"hello set"+returning+nonreturning+" size"+nonreturning.size(),Toast.LENGTH_SHORT ).show();
return nonreturning;
}
Phương pháp chung hơn là biến thể của https://stackoverflow.com/a/52296246
/**
* Returns a duplicated values found in given collection based on fieldClassifier
*
* @param collection given collection of elements
* @param fieldClassifier field classifier which specifies element to check for duplicates(useful in complex objects).
* @param <T> Type of element in collection
* @param <K> Element which will be returned from method in fieldClassifier.
* @return returns list of values that are duplocated.
*/
public static <T, K> List<K> lookForDuplicates(List<T> collection, Function<? super T, ? extends K> fieldClassifier) {
return collection.stream().collect(Collectors.groupingBy(fieldClassifier))
.entrySet()
.stream()
.filter(e -> e.getValue().size() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
Nếu bạn biết giá trị tối đa (ví dụ <10000), bạn có thể hy sinh không gian cho tốc độ. Tôi không thể nhớ chính xác tên của kỹ thuật này.
mã giả:
//does not handle case when mem allocation fails
//probably can be extended to unknown values /larger values .
maybe by sorting first
public List<int> GetDuplicates(int max)
{
//allocate and clear memory to 0/false
bit[] buckets=new bit[max]
memcpy(buckets,0,max);
//find duplicates
List<int> result=new List<int>();
foreach(int val in List)
{
if (buckets[val])
{
result.add(value);
}
else
{
buckets[val]=1;
}
}
return result
}
Hãy thử điều này:
Ví dụ nếu giá trị Danh sách là: [1, 2, 3, 4, 5, 6, 4, 3, 7, 8] mục trùng lặp [3, 4].
Collections.sort(list);
List<Integer> dup = new ArrayList<>();
for (int i = 0; i < list.size() - 1; i++) {
if (list.get(i) == list.get(i + 1)) {
if (!dup.contains(list.get(i + 1))) {
dup.add(list.get(i + 1));
}
}
}
System.out.println("duplicate item " + dup);