java 使用流API从2个不同的整数数组中查找重复项

68bkxrlz  于 2023-09-29  发布在  Java
关注(0)|答案(3)|浏览(141)

我有两个不同的整数数组:

int arr1[] = [1,2,3,4]
int arr2[] = [2,3,5,6]

如何使用Java 8的Stream API从上述2个数组中找到重复项?
在Java 7中,我做了

public class FindDuplicates {
    public static void main(String[] args) {
        int arr1[] = {1, 2, 3, 4};
        int arr2[] = {2, 3, 5, 6};

        // Using two loops to find duplicates
        for (int i = 0; i < arr1.length; i++) {
            for (int j = 0; j < arr2.length; j++) {
                if (arr1[i] == arr2[j]) {
                    System.out.println("Duplicate: " + arr1[i]);
                }
            }
        }
    }
}
eit6fx6z

eit6fx6z1#

为了提高效率,我建议使用set进行缓存。时间复杂度为O(n + m)(其中n和m是arr1和arr2的长度)

int arr1[] = {1, 2, 3, 4};
    int arr2[] = {2, 3, 5, 6};

    //convert arr2 to Set for later quick O(1) lookup
    Set<Integer> set2 = Arrays
            .stream(arr2) // Turn arr2 into IntStream
            .boxed() // boxed() converts IntStream to Stream<Integer>
                     //  this is needed because Set can only hold objects
            .collect(Collectors.toSet()); // Collect all incoming Integer objects into a Set (HashSet<Integer>)
    
    //filter arr1 elements that exist in the set2 (arr2)
    Set<Integer> duplicates = Arrays.stream(arr1) // Turn arr1 into IntStream 
            .boxed()    // boxed() converts IntStream to Stream<Integer>
                        //  this is needed because set2::contains expects an Integer object
            .filter(set2::contains) // Filter out all elements that are not in set2 (*)
            .collect(Collectors.toSet()); // Collect all incoming Integer objects into a Set (HashSet<Integer>) for final results

    System.out.println(duplicates);

(*)set2::contains是方法引用,它等价于lambda表达式(x) -> set2.contains(x)

bqf10yzr

bqf10yzr2#

  • 将两个数组转换为流。
  • 使用filter()只保留arr1中同时存在于arr2中的元素。
  • 将结果收集到列表中。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class duplicate {
public static void main(String[] args) {
    int[] arr1 = {1, 2, 3, 4};
    int[] arr2 = {2, 3, 5, 6};

    List<Integer> duplicates = Arrays.stream(arr1)
            .boxed()
            .filter(i -> Arrays.stream(arr2).anyMatch(j -> j == i))
            .collect(Collectors.toList());

    System.out.println(duplicates);   

}

输出

在上面的代码中:
Arrays.stream(arr1).boxed()将int数组arr1转换为Integer对象流。
filter()方法只保留arr1中同时存在于arr2中的数字。collect()方法将结果收集到列表中。

另一种方式是:

public static void main(String[] args) {
     int[] arr1 = {1, 2, 3, 4};
     int[] arr2 = {2, 3, 5, 6};
        Set<Integer> set1 = IntStream.of(arr1).boxed().collect(Collectors.toSet());
        Set<Integer> intersection = IntStream.of(arr2).boxed()
                                          .filter(set1::contains)
                                          .collect(Collectors.toSet());

        System.out.println("Duplicated elements: " + intersection);
}

*IntStream.of(arr1).boxed()

  • IntStream.of(arr1):这将从arr1数组创建IntStreamint值的流)。
  • .boxed():将IntStream(原始int s的流)转换为Stream<Integer>Integer对象的流)。
    *collect(Collectors.toSet())
  • collect方法是一个终端操作,它将流的元素转换为不同类型的结果或可变约简。
  • Collectors.toSet()是一个收集器,它将输入元素累积到新的Set中。因此,在boxed()之后,它将Integer对象收集到Set<Integer>中。
    *.filter(set1::contains)
  • filter方法是一个中间操作,允许您根据 predicate 从流中筛选元素。
  • set1::contains:这是对set1contains方法的方法引用。这意味着IntStream.of(arr2).boxed()的每个元素都将被传递给set1contains方法,以检查它是否存在于set1中。如果它存在,则意味着它是arr1arr2之间的公共元素。
ars1skjm

ars1skjm3#

你也可以使用set来过滤:

int[] arr1 = {1,2,3,4};
    int[] arr2 = {2,3,4,5,6};

    Set<Integer>  uniqueItems = new HashSet<>();
    List<Integer> dupplicates = Stream.concat(Arrays.stream(arr1).boxed(), Arrays.stream(arr2).boxed())
          .filter(i -> !uniqueItems.add(i))
          .collect(Collectors.toList());

如果一个元素已经在set中,那么调用uniqueItems.add(i)将返回false。

相关问题