Quiero contar con qué frecuencia aparece un elemento de ArrayList "list1" en el otro ArrayList "list2".
Quiero esta salida:
A 2 B 0 C 1 D 2Obtengo esta salida:
A 0 B 0 C 0 D 69¿Podría por favor ayudarme a hacer esto? ¡Gracias!
enter code here HashMap<Character, Integer> map = new HashMap<Character, Integer>(); ArrayList<Character> list1 = new ArrayList<Character>(); ArrayList<Character> list2 = new ArrayList<Character>(); Collections.addAll(list1, 'A', 'B', 'C', 'D'); Collections.addAll(list2, 'D', 'A', 'C', 'A', 'D'); for (int i = 0; i < list1.size(); i++) { for (int j = 0; j < list2.size(); j++) { if (list1.get(i) == list2.get(j)) { map.put(list1.get(i), 1); } if (list1.get(i) == list2.get(j) && (map.containsKey(list1.get(i)))) { map.replace(list1.get(i), list1.get(i) + 1); } if (list1.get(i) != list2.get(j)) { map.put(list1.get(i), 0); } } } System.out.println("Map: "); for (Map.Entry<Character, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue()); }Utilice el método de frequency , de Colección , a saber:
for (Character c : list1) map.put(c, Collections.frequency(list2, c)); System.out.println("Map: "); for (Map.Entry<Character, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue()); }Si eres fanático de los one liners:
list1.forEach(c -> map.put(c, Collections.frequency(list2, c)));Incluyendo la impresión de los elementos:
list1.forEach(c -> System.out.printf("%s %d%n", c, Collections.frequency(list2, c)));Por cierto, tu respuesta original era casi correcta, solo tenías que repensar un poco los condicionales y su orden:
for (Character c1 : list1) { for (Character c2 : list2) { if(map.containsKey(c1) && c1 == c2 ){ map.put(c1, map.get(c1) + 1); } else if (!map.containsKey(c1) && c1 != c2 ) { map.put(c1, 0); } else if (!map.containsKey(c1) && c1 == c2) { map.put(c1, 1); } } } Otro consejo es que, si no necesita explícitamente el índice de bucle, es mejor usar la expresión for (Character c1 : list1) en lugar de for(int i = 0; i < list1.size(); i++) . La primera es más limpia y menos propensa a errores que la segunda versión. Además, puede usar la variable c1 en lugar de tener que hacer list1.get(i) todo el tiempo.
Puede usar Stream API introducido en Java 8 para realizar esta tarea. Aquí hay un código de ejemplo que resuelve el problema:
final List<Character> list1 = new ArrayList<Character>(); final List<Character> list2 = new ArrayList<Character>(); Collections.addAll(list1, 'A', 'B', 'C', 'D'); Collections.addAll(list2, 'D', 'A', 'C', 'A', 'D'); final Map<Character, Integer> map = new HashMap<>(); for (final Character c : list1) { final int occurrences = (int) list2.stream().filter(c::equals).count(); map.put(c, occurrences); } System.out.println("Map: "); for (Map.Entry<Character, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue()); }Nota: Para este grupo de problemas, le recomiendo que comience la implementación escribiendo algunas pruebas unitarias.
Una solución más limpia de Java 8 sin bucles adicionales sería:
List<Character> list1 = Arrays.asList('A', 'B', 'C', 'D'); List<Character> list2 = Arrays.asList('D', 'A', 'C', 'A', 'D'); Map<Character, Integer> map = list1.stream() .collect(Collectors.toMap( c -> c, c -> Collections.frequency(list2, c) )); // print entire map System.out.println(map); // print formatted map map.entrySet().forEach(e -> System.out.printf("%s %d%n", e.getKey(), e.getValue()));Si la tarea específica es imprimir las frecuencias, el mapa intermedio se puede omitir por completo :)
list1.stream() .map(c -> new StringBuilder() .append(c).append(' ') .append(Collections.frequency(list2, c)) ) .forEach(System.out::println);