18Cosa sono i generics e cos'è la cancellazione dei tipi (type erasure)?
I generics permettono al codice di esprimere contenitori e API type-safe, come List<String>. A tempo di compilazione, il compilatore controlla i tipi e inserisce i cast dove necessario. A tempo di esecuzione, la maggior parte delle informazioni sui tipi generici viene cancellata, quindi List<String> e List<Integer> condividono la stessa classe a runtime. Questo è il motivo per cui non è possibile creare direttamente un new T(), usare parametri di tipo primitivo, o controllare in modo affidabile instanceof List<String>.
List<String> names = new ArrayList<>();
names.add("Alice");
List<? extends Number> producer;
List<? super Integer> consumer;
Prova a rispondere a questa domanda con un coach IA
19Cos'è il Java Collections Framework?
Il Collections Framework è un insieme di interfacce e implementazioni per memorizzare ed elaborare gruppi di oggetti. Le interfacce principali includono List, Set, Queue, Deque e Map. Le implementazioni includono ArrayList, LinkedList, HashSet, TreeSet, HashMap, TreeMap e PriorityQueue. La scelta di una collezione si basa sul modello di accesso, sui requisiti di ordinamento, sull'unicità, sulla complessità di ricerca, sull'overhead di memoria e sulle esigenze di concorrenza.
List<String> list = new ArrayList<>();
Set<Long> ids = new HashSet<>();
Map<Long, User> usersById = new HashMap<>();
Deque<String> queue = new ArrayDeque<>();
Prova a rispondere a questa domanda con un coach IA
20Come funziona HashMap?
HashMap memorizza le entry in bucket selezionati tramite un hash della chiave. Per la ricerca, calcola l'hash, trova il bucket e confronta le chiavi utilizzando equals. Le collisioni vengono gestite all'interno del bucket; nel Java moderno, le catene lunghe possono essere convertite in un albero bilanciato (treeified) quando si soddisfano determinate condizioni. HashMap consente un'unica chiave null e valori null, non è thread-safe e può ridimensionarsi (resize) quando viene superata la soglia del fattore di carico (load factor).
Map<Long, User> users = new HashMap<>();
users.put(user.id(), user);
User found = users.get(user.id());
Prova a rispondere a questa domanda con un coach IA
21Qual è la differenza tra HashMap, LinkedHashMap, TreeMap e ConcurrentHashMap?
HashMap fornisce un accesso rapido e non ordinato e non è thread-safe. LinkedHashMap mantiene l'ordine di inserimento o l'ordine di accesso ed è utile per cache di tipo LRU (Least Recently Used). TreeMap mantiene le chiavi ordinate secondo l'ordine naturale o tramite un Comparator e garantisce operazioni con complessità O(log n). ConcurrentHashMap è progettata per l'accesso concorrente con sincronizzazione segmentata/interna, non consente chiavi o valori null ed è preferibile a synchronizedMap sotto carico.
map.computeIfAbsent(key, ignored -> loadValue());
Prova a rispondere a questa domanda con un coach IA
22Qual è la differenza tra ArrayList e LinkedList?
ArrayList è basata su un array. Fornisce un accesso indicizzato rapido, un layout di memoria compatto e un'iterazione efficiente, ma l'inserimento nel mezzo richiede lo spostamento degli elementi. LinkedList è una lista doppiamente concatenata. Ha un costo di inserimento minore se il nodo è già noto, ma l'accesso indicizzato ha una complessità O(n), l'overhead di memoria è maggiore e la località della cache è peggiore. In molte applicazioni reali ArrayList risulta più veloce, anche quando sono previsti alcuni inserimenti.
Prova a rispondere a questa domanda con un coach IA
23Qual è la differenza tra `Comparable` e `Comparator`?
`Comparable` definisce l'ordinamento naturale all'interno della classe tramite `compareTo`. `Comparator` è un oggetto separato o una lambda che definisce un ordinamento esterno. `Comparable` è utile quando un tipo ha un ovvio ordinamento predefinito. `Comparator` è preferibile quando esistono molteplici criteri di ordinamento, ad esempio per nome, data o priorità. `compare` e `compareTo` devono essere coerenti e preferibilmente compatibili con `equals` quando usati in set o mappe ordinate.
class User implements Comparable<User> {
private int age;
@Override
public int compareTo(User other) {
return Integer.compare(age, other.age);
}
}
Comparator<User> byName =
Comparator.comparing(User::getName);
Comparator<User> byAgeThenName =
Comparator.comparingInt(User::getAge)
.thenComparing(User::getName);
Prova a rispondere a questa domanda con un coach IA