百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Java数组与列表去重的18种方法

toyiye 2024-05-25 20:11 17 浏览 0 评论

说明

在实际编程中,经常会遇到数组或列表去掉重复项,以保持成员唯一性。各个语言的实现方式均不尽相同。针对数组去重,Java实现方式有多种,比如新建数组来存储非重复项,或者在原有基础上删除掉重复的项,也可以利用数据结构Set或ArrayList来达到去重复。以下18种方式都可以实现,但每一种方法都不尽相同,有的很简单,几行代码搞定,有的则稍复杂,需要10来行代码。通过对比不同的实现,我们可以从中发现Java语言里一些不同的东西。

方式

// 1. 双循环遍历全部成员,将当前项目与左边项逐个进行对比,如果值相同且下标相同表示唯一,其他则认为是重复项进行忽略。
static int[] unique1(int arr[]) {
  int newArr[] = new int[arr.length];
  int x = 0;
  for (int i = 0, l = arr.length; i < l; i++) {
    for (int j = 0; j <= i; j++) {
      if (arr[i] == arr[j]) {
        if (i == j) {
          newArr[x] = arr[i];
          x++;
        }
        break;
      }
    }
  }
  int result[] = Arrays.copyOf(newArr, x);
  return result;
}


// 2. 先将数组转换为List,利用List的indexOf方法查找下标,当下标匹配时表示唯一,添加到新列表中
static Integer[] unique2(Integer arr[]) {
  int x = 0;
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  int l = list.size();
  for (int i = 0; i < l; i++) {
    if (list.indexOf(arr[i]) == i) {
      list.add(arr[i]);
      x++;
    }
  }
  // 返回取出的非重复项
  Integer[] result = new Integer[x];
  return list.subList(list.size() - x, list.size()).toArray(result);
}


// 3. 在原有列表上移除重复项目。自后往前遍历,逐个与前面项比较,如果值相同且下标相同,则移除当前项。
static Integer[] unique3(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  int l = list.size();
  while (l-- > 0) {
    int i = l;
    while (i-- > 0) {
      if (list.get(l).equals(list.get(i))) {
        list.remove(l);
        break;
      }
    }
  }
  return list.toArray(new Integer[list.size()]);
}


// 4. 在原有列表上移除重复项目。自前往后遍历,逐个与前面项比较,如果值相同且下标相同,则移除前面项。
static Integer[] unique4(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  int l = list.size();

  for (int i = 1; i < l; i++) {
    for (int j = 0; j < i; j++) {
      if (list.get(i).equals(list.get(j))) {
        list.remove(i);
        i--;
        l--;
        break;
      }
    }
  }
  return list.toArray(new Integer[list.size()]);
}


// 5. 在原有列表上移除重复项目。自前往后遍历,逐个与后面项比较,如果值相同且下标相同,则移除当前项。
static Integer[] unique5(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  int l = list.size();
  for (int i = 0; i < l; i++) {
    for (int j = i + 1; j < l; j++) {
      if (list.get(i).equals(list.get(j))) {
        list.remove(j);
        i--;
        l--;
        break;
      }
    }
  }
  return list.toArray(new Integer[list.size()]);
}


// 6. 利用hashMap属性唯一性来实现去重复。
static Integer[] unique6(Integer arr[]) {
  Map<Object, Integer> map = new HashMap<Object, Integer>();

  for (Integer item : arr) {
    if (map.containsKey(item)) {
      continue;
    }
    map.put(item, item);
  }

  List<Integer> list = new ArrayList<>(map.values());
  return list.toArray(new Integer[list.size()]);
}


// 7. 利用filter表达式,即把不符合条件的过滤掉。需要借助外部列表存储不重复项。
static List<Integer> unique7newArr = new ArrayList<>();

static boolean unique7contains(Integer item) {
  if (unique7newArr.indexOf(item) < 0) {
    unique7newArr.add(item);
    return true;
  }
  return false;
}

static Integer[] unique7(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  return list.stream().filter(UniqueArray::unique7contains).collect(Collectors.toList())
    .toArray(new Integer[UniqueArray.unique7newArr.size()]);
}


// 8. 利用hashSet数据结构直接去重复项。无序非同步。
static Integer[] unique8(Integer arr[]) {
  System.out.print("covert to steam first then to set: ");
  Arrays.asList(arr).stream().collect(Collectors.toSet()).forEach(System.out::print);
  System.out.println("\ndirectly convert to set:");
  Set<Integer> set = new HashSet<>(Arrays.asList(arr));
  return new ArrayList<>(set).toArray(new Integer[set.size()]);
}


// 9. 利用LinkedHashSet数据结构直接去重复项。有序链表。
static Integer[] unique9(Integer arr[]) {
  Set<Integer> linkedHashSet = new LinkedHashSet<>(Arrays.asList(arr));
  return new ArrayList<>(linkedHashSet).toArray(new Integer[linkedHashSet.size()]);
}


// 10. 利用TreeSet数据结构直接去重复项。自然排序和定制排序。
static Integer[] unique10(Integer arr[]) {
  Set<Integer> treeSet = new TreeSet<>(Arrays.asList(arr)).descendingSet();
  return new ArrayList<>(treeSet).toArray(new Integer[treeSet.size()]);
}


// 11. 提前排序,从后向前遍历,将当前项与前一项对比,如果重复则移除当前项
static Integer[] unique11(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  Collections.sort(list);
  for (int l = list.size() - 1; l > 0; l--) {
    if (list.get(l).equals(list.get(l - 1))) {
      list.remove(l);
    }
  }
  return new ArrayList<>(list).toArray(new Integer[list.size()]);
}


// 12. 提前排序,自前往后遍历,将当前项与后一项对比,如果重复则移除当前项
static Integer[] unique12(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  Collections.sort(list, Collections.reverseOrder());
  int l = list.size() - 1;
  for (int i = 0; i < l; i++) {
    if (list.get(i).equals(list.get(i + 1))) {
      list.remove(i);
      i--;
      l--;
    }
  }
  return new ArrayList<>(list).toArray(new Integer[list.size()]);
}


// 13. 转为stream,利用distinct方法去重复
static Integer[] unique13(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  list = list.stream().distinct().collect(Collectors.toList());
  return new ArrayList<>(list).toArray(new Integer[list.size()]);
}


// 14. 双循环自右往左逐个与左侧项对比,如遇相同则跳过当前项,下一项为当前项,继续逐个与左侧项对比
static Integer[] unique14(Integer arr[]) {
  int len = arr.length;
  Integer[] result = new Integer[len];
  int x = len;
  for (int i = len - 1; i >= 0; i--) {
    for (int j = i - 1; j >= 0; j--) {
      if (arr[i].equals(arr[j])) {
        i--;
        j = i;
      }
    }
    // 非重复项的为唯一,追加到新数组
    result[--x] = arr[i];
  }
  return Arrays.copyOfRange(result, x, len);
}


// 15. 利用Interator来遍历List,如果不在新列表中则添加
static Integer[] unique15(Integer arr[]) {
  List<Integer> list = new ArrayList<>(Arrays.asList(arr));
  List<Integer> result = new ArrayList<>();
  Iterator<Integer> it = list.iterator();
  while (it.hasNext()) {
    Integer item = it.next();
    if (!result.contains(item)) {
      result.add(item);
    }
  }
  return new ArrayList<>(result).toArray(new Integer[result.size()]);
}


// 16. 利用递归调用来去重复。递归自后往前逐个调用,当长度为1时终止。
// 当后一项与前任一项相同说明有重复,则删除当前项。相当于利用自我调用来替换循环
static Integer[] uniqueRecursion1(Integer arr[], int len, List<Integer> result) {
  int last = len - 1;
  Integer lastItem = arr[last];
  int l = last;
  boolean isRepeat = false;
  if (len <= 1) {
    result.add(0, lastItem);
    return new ArrayList<>(result).toArray(new Integer[result.size()]);
  }
  while (l-- > 0) {
    if (lastItem.equals(arr[l])) {
      isRepeat = true;
      break;
    }
  }
  // 如果不重复表示唯一,则添加到新数组中
  if (!isRepeat) {
    result.add(0, lastItem);
  }
  return uniqueRecursion1(arr, len - 1, result);
}


// 17. 利用递归调用来去重复的另外一种方式。递归自后往前逐个调用,当长度为1时终止。
// 与上一个递归不同,这里将不重复的项目作为结果拼接起来
static List<Integer> uniqueRecursion2(List<Integer> arr, int len) {
  if (len <= 1) {
    System.out.println("last arr:" + arr);
    return arr;
  }

  int last = len - 1;
  int l = last - 1;
  boolean isRepeat = false;
  Integer lastItem = arr.get(last);
  while (l >= 0) {
    if (lastItem.equals(arr.get(l))) {
      isRepeat = true;
      break;
    }
    l--;
  }

  // 如果不重复则添加到临时列表,最后将全部结果拼接
  List<Integer> result = new ArrayList<>();
  arr.remove(last);
  if (!isRepeat) {
    result.add(lastItem);
  }
  return Stream.concat(uniqueRecursion2(arr, len - 1).stream(), result.stream()).collect(Collectors.toList());
}


// 18. 双重循环,将左侧项逐个与当前项比较。如果遇到值想等则比较下标,下标相同则追加到新数组。这里与第1个方案稍微的不同。
static Integer[] unique18(Integer arr[]) {
  Integer newArr[] = new Integer[arr.length];
  int x = 0;
  for (int i = 0; i < arr.length; i++) {
    int j = 0;;
    for (; j < i; j++) {
      if (arr[i].equals(arr[j])) {
        break;
      }
    }
    if (i == j) {
      newArr[x] = arr[i];
      x++;
    }
  }
  return Arrays.copyOf(newArr, x);
}

执行测试

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class UniqueArray {
  
 // 此处省略代码...

public static void main(final String args[]) {
    int arr1[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    int[] result;
    long startTime;
      int arr1[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    int[] result;
    long startTime;
    // 1.
    System.out.println("unique1 start:" + Arrays.toString(arr1));
    startTime = System.currentTimeMillis();
    result = UniqueArray.unique1(arr1);
    System.out.println("unique1 result:" + Arrays.toString(result));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 2.
    Integer arr2[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique2 start:" + Arrays.toString(arr2));
    startTime = System.currentTimeMillis();
    Integer result2[] = UniqueArray.unique2(arr2);
    System.out.println("unique2 result:" + Arrays.toString(result2));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 3.
    Integer arr3[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique3 start:" + Arrays.toString(arr2));
    startTime = System.currentTimeMillis();
    Integer result3[] = UniqueArray.unique3(arr3);
    System.out.println("unique3 result:" + Arrays.toString(result3));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 4.
    Integer arr4[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique4 start:" + Arrays.toString(arr4));
    startTime = System.currentTimeMillis();
    Integer result4[] = UniqueArray.unique4(arr4);
    System.out.println("unique4 result:" + Arrays.toString(result4));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 5.
    Integer arr5[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique5 start:" + Arrays.toString(arr5));
    startTime = System.currentTimeMillis();
    Integer result5[] = UniqueArray.unique5(arr5);
    System.out.println("unique5 result:" + Arrays.toString(result5));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 6.
    Integer arr6[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique6 start:" + Arrays.toString(arr6));
    startTime = System.currentTimeMillis();
    Integer result6[] = UniqueArray.unique6(arr6);
    System.out.println("unique6 result:" + Arrays.toString(result6));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 7.
    Integer arr7[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique7 start:" + Arrays.toString(arr7));
    startTime = System.currentTimeMillis();
    Integer result7[] = UniqueArray.unique7(arr7);
    System.out.println("unique7 result:" + Arrays.toString(result7));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 8.
    Integer arr8[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique8 start:" + Arrays.toString(arr8));
    startTime = System.currentTimeMillis();
    Integer result8[] = UniqueArray.unique8(arr8);
    System.out.println("unique8 result:" + Arrays.toString(result8));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 9.
    Integer arr9[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique9 start:" + Arrays.toString(arr9));
    startTime = System.currentTimeMillis();
    Integer result9[] = UniqueArray.unique9(arr9);
    System.out.println("unique9 result:" + Arrays.toString(result9));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 10.
    Integer arr10[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique10 start:" + Arrays.toString(arr10));
    startTime = System.currentTimeMillis();
    Integer result10[] = UniqueArray.unique10(arr10);
    System.out.println("unique10 result:" + Arrays.toString(result10));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 11.
    Integer arr11[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique11 start:" + Arrays.toString(arr11));
    startTime = System.currentTimeMillis();
    Integer result11[] = UniqueArray.unique11(arr11);
    System.out.println("unique11 result:" + Arrays.toString(result11));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 12.
    Integer arr12[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique12 start:" + Arrays.toString(arr12));
    startTime = System.currentTimeMillis();
    Integer result12[] = UniqueArray.unique12(arr12);
    System.out.println("unique12 result:" + Arrays.toString(result12));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 13.
    Integer arr13[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique13 start:" + Arrays.toString(arr13));
    startTime = System.currentTimeMillis();
    Integer result13[] = UniqueArray.unique13(arr13);
    System.out.println("unique13 result:" + Arrays.toString(result13));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 14.
    Integer arr14[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique14 start:" + Arrays.toString(arr14));
    startTime = System.currentTimeMillis();
    Integer result14[] = UniqueArray.unique14(arr14);
    System.out.println("unique14 result:" + Arrays.toString(result14));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 15.
    Integer arr15[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique15 start:" + Arrays.toString(arr15));
    startTime = System.currentTimeMillis();
    Integer result15[] = UniqueArray.unique15(arr15);
    System.out.println("unique15 result:" + Arrays.toString(result15));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 16.
    Integer arr16[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("uniqueRecursion1 start:" + Arrays.toString(arr16));
    startTime = System.currentTimeMillis();
    Integer result16[] = UniqueArray.uniqueRecursion1(arr16, arr16.length, new ArrayList<>());
    System.out.println("uniqueRecursion1 result:" + Arrays.toString(result16));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 17.
    Integer arr17[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("uniqueRecursion2 start:" + Arrays.toString(arr17));
    startTime = System.currentTimeMillis();
    List<Integer> result17 = UniqueArray.uniqueRecursion2(new ArrayList<>(Arrays.asList(arr17)), arr17.length);
    System.out.println("uniqueRecursion2 result:" + result17);
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

    // 18.
    Integer arr18[] = { 1, 3, -1, 1, 2, 2, 4, 2, 2, -1 };
    System.out.println("unique18 start:" + Arrays.toString(arr18));
    startTime = System.currentTimeMillis();
    Integer result18[] = UniqueArray.unique18(arr18);
    System.out.println("unique18 result:" + Arrays.toString(result18));
    System.out.println("\r\ntime:" + (System.currentTimeMillis() - startTime) + " ms.");

打印结果


 MacBook-Pro:unique jarry$ java --version java 10.0.1 2018-04-17
 Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10) Java HotSpot(TM)
 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

MacBook-Pro:unique jarry$ javac UniqueArray.java 
MacBook-Pro:unique jarry$ java UniqueArray
unique1 start:[1, 3, -1, 1, 2, 2, 4, 2, 2, -1]
unique1 result:[1, 3, -1, 2, 4]

time:1 ms.
unique2 start:[1, 3, -1, 1, 2, 2, 4, 2, 2, -1]
unique2 result:[1, 3, -1, 2, 4]

// ...其他省略...etc

time:0 ms.
uniqueRecursion2 start:[1, 3, -1, 1, 2, 2, 4, 2, 2, -1]
last arr:[1]
uniqueRecursion2 result:[1, 3, -1, 2, 4]

time:1 ms.
unique18 start:[1, 3, -1, 1, 2, 2, 4, 2, 2, -1]
unique18 result:[1, 3, -1, 2, 4]


思考

通过去重复的多种实现,其实是让我们更了解Java语言,还可以让我们根据场景采用不用方式,毕竟业务场景千差万别。你常用哪几种方式?你还有其他的实现方式吗?

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码