Live Coding Java — Cheat Sheet

Tag: java, algorithms, streams, collections, data structures, coding

Livello: intermedio

TL;DR: Pattern essenziali e strutture dati pronte all'uso per risolvere problemi di algoritmi in Java, puntando su leggibilità e performance.

Concetti chiave

Sfruttare java.util.stream.Stream per filtrare, mappare e ridurre collezioni in modo conciso.

Usare sempre StringBuilder invece della concatenazione manuale nei cicli per evitare memory leak di stringhe immutabili.

Ottimizzare i conteggi di frequenza con i metodi Map.computeIfAbsent e Map.merge.

Utilizzare HashSet per operazioni di lookup veloci con complessità O(1).

Adottare i record per creare rapidamente DTO o nodi di supporto immutabili senza boilerplate code.

Preferire ArrayDeque a Stack o LinkedList per implementare code (FIFO) e pile (LIFO).

Ricordare l'uso dei metodi factory come List.of(), Set.of() e Map.of() per inizializzare dati di test.

Domande tipiche e risposte pronte

Q: Come inverti una stringa o verifichi se è palindroma senza cicli manuali?R: Uso direttamente new StringBuilder(str).reverse().toString() e verifico l'uguaglianza con equals().

Q: Come trovi gli elementi duplicati in una lista o array?R: Aggiungo gli elementi in un HashSet; il metodo add() restituisce false se l'elemento è già presente.

Q: Perché preferisci ArrayList rispetto a LinkedList per questa iterazione?R: Perché ArrayList offre accesso posizionale O(1) e garantisce una migliore cache locality in memoria.

Insidie e errori comuni

Dimenticare la gestione di array vuoti, liste vuote o parametri null in ingresso.

Utilizzare l'operatore == invece del metodo .equals() per confrontare il valore degli oggetti (specialmente le stringhe).

Modificare strutturalmente una collezione tramite ciclo for-each (scatena ConcurrentModificationException).

Non considerare l'overflow dei tipi primitivi (es. usare int invece di long per la somma di array di grandi dimensioni).

Iniziare a scrivere classi e interfacce complesse quando basta un metodo statico essenziale.

Snippet e comandi

// Conteggio delle occorrenze in una lista tramite Stream
Map<String, Long> frequenze = list.stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

// Incrementare un contatore in una mappa in modo sicuro
Map<Integer, Integer> counter = new HashMap<>();
for (int num : nums) {
    counter.merge(num, 1, Integer::sum);
}

// Ordinamento custom di array o liste
Arrays.sort(arr, Comparator.comparingInt(String::length).reversed());

// Conversione rapida tra array primitivi e collezioni
List<Integer> list = Arrays.stream(primitiveArray).boxed().toList();
int[] newArray = list.stream().mapToInt(Integer::intValue).toArray();

Da ripassare

[ ] Implementazione manuale di Binary Search per array ordinati (Arrays.binarySearch).

[ ] Sintassi avanzata dei Collectors (es. partitioningBy, mapping).

[ ] Costruzione e attraversamento di un albero binario usando classi annidate.

Jarvis Interviews
Jarvis