¿Sigues usando list.contain para hacer la deduplicación? ¡Es tiempo de cambiar!

387092cfeafc65507a851f36b30f644f.jpeg

Fuente: blog.csdn.net/qq_35387940/article/details/129885310

Recientemente, fue otra ronda de revisión del código y se encontró un código para lograr la deduplicación, usando list.contain  …

ace7fed6be93274b8443aab6c61c9dc3.png

Reflexioné, ¿es cierto que muchos principiantes también tienen este problema de deduplicación?

Así que elegí resolver este asunto y compartirlo.

El primero es crear una lista <String> de datos simulados, un total de elementos de 2W y la mitad de los elementos de 1W de datos se repiten:

public static List<String> getTestList() {
    List<String> list = new ArrayList<>();
    for (int i = 1; i <= 10000; i++) {
        list.add(String.valueOf(i));
    }
    for (int i = 10000; i >= 1; i--) {
        list.add(String.valueOf(i));
    }
    return list;
}

Echemos un vistazo al código que usamos para deduplicar con contiene:

/**
 * 使用 list.contain 去重
 *
 * @param testList
 */
private static void useContain2Distinct(List<String> testList) {
    System.out.println("contains 开始去重,条数:" + testList.size());
    List<String> testListDistinctResult = new ArrayList<>();
    for (String str : testList) {
        if (!testListDistinctResult.contains(str)) {
            testListDistinctResult.add(str);
        }
    }
    System.out.println("contains 去重完毕,条数:" + testListDistinctResult.size());
}

Llamemoslo para ver cuanto tarda:

public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    useContainDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

pérdida de tiempo:

f9ac8e41c54papá5aa65ca1ad7179papá9.png

Evaluación: la eficiencia de list.contain, mi sugerencia es, solo conózcalo, no lo use.

Es bien sabido que Set no tiene datos duplicados, así que echemos un vistazo al rendimiento del uso de HashSet para deduplicar:

pd: aquí es para usar el método add de set para hacer la deduplicación

/**
 * 使用set去重
 *
 * @param testList
 */
private static void useSetDistinct(List<String> testList) {
    System.out.println("HashSet.add 开始去重,条数:" + testList.size());
    List<String> testListDistinctResult = new ArrayList<>(new HashSet(testList));
    System.out.println("HashSet.add 去重完毕,条数:" + testListDistinctResult.size());
}

Llamemoslo para ver cuanto tarda:

public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    useSetDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

pérdida de tiempo:

26309220b368af2d166f188a01c56b89.png

Evaluación: La eficiencia de HashSet, se recomienda mi sugerencia.

Hemos creado un grupo de intercambio técnico de alta calidad. Cuando estés con personas excelentes, tú mismo te convertirás en excelente. Date prisa y haz clic para unirte al grupo y disfrutar de la alegría de crecer juntos.

¿Por qué hay una diferencia de tiempo tan grande?

No hay mucho que decir, veamos el código fuente:

lista.contiene(o):

18b38def7153195669d6ef37d73e1e81.png

Puedes ver que index(o) se usa en él:

525f44c24651a36841a766d61d807e73.png

Complejidad temporal: O(n) n: número de elementos

Entonces, veamos cómo se ve set.add(o):

29e700124074135110283f9006ee71a8.png

La adición del mapa, no hablaré de los clichés, el hash se mete directamente en una determinada posición, la complejidad del tiempo: O(1).

Entonces, O(n) u O(1), ¿cuál es más rápido y cuál es más lento? Obviamente.

5eacc4eabd178007568d972334da7384.png

pd: hablemos del contenido de hashset

6cab391e404d3ebdaa2e33f76d527c21.png

La complejidad del tiempo también es: O(1)

05a58666a5f91f5158111c285e389786.png

Luego, veamos finalmente otra deduplicación:

Duplicar bucle for, eliminar para deduplicación

/**
 * 使用双for循环去重
 * @param testList
 */
private static void use2ForDistinct(List<String> testList) {
    System.out.println("list 双循环 开始去重,条数:" + testList.size());
    for (int i = 0; i < testList.size(); i++) {
        for (int j = i + 1; j < testList.size(); j++) {
            if (testList.get(i).equals(testList.get(j))) {
                testList.remove(j);
            }
        }
    }
    System.out.println("list 双循环  去重完毕,条数:" + testList.size());
}
public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    use2ForDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

pérdida de tiempo:

bbddc0e38ced590d514be6b2056cc956.png

Evaluación: solo conózcalo, solo diviértase, no lo use, es lento y el código se ve desordenado

Deduplicación distinta de Stream:

/**
 * 使用Stream 去重
 *
 * @param testList
 */
private static void useStreamDistinct(List<String> testList) {
    System.out.println("stream 开始去重,条数:" + testList.size());
    List<String> testListDistinctResult = testList.stream().distinct().collect(Collectors.toList());
    System.out.println("stream 去重完毕,条数:" + testListDistinctResult.size());
}
public static void main(String[] args) {
    List<String> testList = getTestList();
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    useStreamDistinct(testList);
    stopWatch.stop();
    System.out.println("去重 最终耗时" + stopWatch.getTotalTimeMillis());
}

pérdida de tiempo:

56516f5f3b75cd7746140dd7f74e8548.png

Evaluación: No está mal, la razón principal es que el código es bastante conciso, un poco tentador.

Finalmente, si tiene otros métodos eficientes de deduplicación, compártalos en el área de mensajes ~

------

Hemos creado un grupo de intercambio técnico de alta calidad. Cuando estés con personas excelentes, tú mismo te convertirás en excelente. Date prisa y haz clic para unirte al grupo y disfrutar de la alegría de crecer juntos. Además, si quieres cambiar de trabajo recientemente, pasé 2 semanas al año recopilando una ola de experiencia cara a cara de grandes fábricas. Si planeas cambiar de trabajo después del festival, ¡puedes hacer clic aquí para reclamarlo !

Lectura recomendada

··································

Hola soy DD programador, llevo 10 años desarrollando driver veterano, MVP de Alibaba Cloud, TVP de Tencent Cloud. Desde desarrollo general hasta arquitecto y socio. En el camino, mi sentimiento más profundo es que debemos seguir aprendiendo y prestar atención a la frontera. Siempre que pueda perseverar, pensar más, quejarse menos y trabajar duro, ¡será fácil adelantar en las curvas! Así que no me preguntes si es demasiado tarde para hacer lo que hago ahora. Si eres optimista sobre algo, debes perseverar para ver esperanza, no perseverar solo cuando veas esperanza. Créeme, mientras te apegues a ello, ¡serás mejor que ahora! Si aún no tiene una dirección, puede seguirme primero y, a menudo, compartiré información de vanguardia aquí para ayudarlo a acumular capital para tomar curvas y adelantar.

Supongo que te gusta

Origin blog.csdn.net/j3T9Z7H/article/details/131198582
Recomendado
Clasificación