
89. En quoi une ArrayList est-elle différente d'une LinkedList ?
C'est l'une des questions les plus populaires, avec celle sur la structure interne d'un HashMap . Aucun entretien n'est complet sans cela, votre réponse devrait donc facilement sortir de votre langue. En plus de l'évidence (ils portent des noms différents), ils diffèrent par leur structure interne. Plus tôt, nous avons discuté de la structure interne d' ArrayList et de LinkedList , je ne vais donc pas entrer dans les détails de leur implémentation. Je rappelle juste qu'ArrayList est implémenté à l'aide d'un tableau interne dont la taille augmente dynamiquement selon cette formule :
<size of the current array> * 3 / 2 + 1
De plus, l'implémentation d'une LinkedList utilise une liste interne doublement chaînée, c'est-à-dire que chaque élément a une référence aux éléments précédent et suivant, à l'exception des éléments situés au début et à la fin de la liste. Les enquêteurs adorent poser cette question comme celle-ci : « Quel est le meilleur, ArrayList ou LinkedList ? » en espérant t'attraper. Après tout, si vous dites que l’un ou l’autre est meilleur, alors vous avez donné la mauvaise réponse. 
-
Si aucun index n'est spécifié, un nouvel élément sera automatiquement ajouté à la fin pour les deux types de listes. Dans une LinkedList , le nouvel élément deviendra la nouvelle queue (seule une paire de références sera réécrite, donc la complexité algorithmique est O(1) ).
La méthode add ajoute un élément à la dernière cellule vide du tableau ( O(1) ).
-
Ajouter un élément par index signifie généralement l'insérer quelque part au milieu de la liste. Dans une LinkedList , la méthode recherchera d'abord l'emplacement souhaité en itérant sur les éléments de la queue et de la tête ( O(n/2) ) et insérera ensuite la valeur en écrasant les références des éléments des deux côtés de l'endroit où se trouve le un nouvel élément est inséré ( O(1) ). La complexité algorithmique globale de cette opération sera O(n/2) .
Dans la même situation (ajout par index), une ArrayList trouve l'emplacement souhaité ( O(1) ) puis décale tous les éléments situés à droite (y compris l'élément déjà stocké à l'index spécifié) vers la droite d'un (ce qui peut nécessiter la création d'un nouveau tableau interne et la copie d'éléments dessus) ( O(n/2) ). La complexité globale est O(n/2) .
-
Ajouter un élément au début d'une LinkedList est similaire à ajouter un élément à la fin : le nouvel élément devient la nouvelle tête ( O(1) ). Mais pour un ArrayList, cette opération nécessite de déplacer tous les éléments vers la droite ( O(n) ).
90. En quoi une ArrayList est-elle différente d'un HashSet ?
Si nous pouvions comparer ArrayList et LinkedList opération par opération pour déterminer laquelle est la meilleure, nous ne trouverions pas si facile de faire une telle comparaison entre ArrayList et HashSet , car ce sont des collections complètement différentes. Vous pouvez comparer un dessert avec un autre, mais comparer un dessert et un plat salé est un défi : ils sont terriblement différents. Je vais néanmoins essayer de souligner certaines des différences entre eux :-
ArrayList implémente l' interface List tandis que HashSet implémente l' interface Set .
-
ArrayList vous permet d'accéder à un élément par index : l' opération get a une complexité algorithmique O(1) , mais HashSet vous permet uniquement d'accéder à un élément souhaité par itération, ce qui donne une complexité algorithmique allant de O(1) à O(n) .
-
ArrayList autorise les éléments en double. Dans un HashSet , tous les éléments sont uniques : toute tentative d'ajout d'un élément déjà présent dans un HashSet échouera (les doublons sont vérifiés par hashcode, d'où le nom de cette collection).
-
ArrayList est implémenté à l'aide d'un tableau interne, mais HashSet est implémenté à l'aide d'un HashMap interne .
-
ArrayList conserve l'ordre d'insertion des éléments, mais HashSet est un ensemble non ordonné et ne conserve pas l'ordre des éléments.
-
ArrayList autorise n'importe quel nombre de valeurs nulles, mais vous ne pouvez ajouter qu'une seule valeur nulle à un HashSet (après tout, les éléments doivent être uniques).
91. Pourquoi Java a-t-il autant d'implémentations de tableaux dynamiques différentes ?
Il s'agit plutôt d'une question philosophique. On pourrait également se demander pourquoi inventent-ils autant de technologies nouvelles et variées ? Pour plus de commodité. Et la même chose est vraie pour un grand nombre d’implémentations de tableaux dynamiques. Aucune d’entre elles ne peut être qualifiée de mise en œuvre la meilleure ou idéale. Chacune a ses avantages dans des situations spécifiques. Notre métier est de connaître leurs différences et leurs forces/faiblesses afin de pouvoir utiliser la collection la plus adaptée à chaque situation donnée.92. Pourquoi Java a-t-il autant d'implémentations différentes de stockage clé-valeur ?
Ici, la situation est la même que pour les implémentations de tableaux dynamiques. Il n’y en a certainement aucun qui soit universellement meilleur que les autres : chacun a des forces et des faiblesses. Et nous devons bien entendu tirer le meilleur parti de leurs atouts. Exemple : le package concurrent, qui possède de nombreuses classes multithread, possède ses propres collections concurrentes . La classe ConcurrentHashMap présente un avantage par rapport à la classe HashMap standard en termes de sécurité lorsque vous travaillez avec des données dans un environnement multithread, mais cela se fait au prix de performances plus lentes. Et les implémentations qui ne constituent pas le meilleur choix dans n’importe quelle situation cessent progressivement d’être utilisées. Par exemple : Hashtable , qui était initialement destiné à être un HashMap thread-safe , a été oublié et n'est plus utilisé, car ConcurrentHashMap est encore meilleur que Hashtable lorsque vous travaillez dans un environnement multithread.93. Comment trier une collection d'éléments ?
La première chose à dire est que la classe représentant les éléments de la collection doit implémenter l' interface Comparable , qui consiste en la méthode compareTo . Ou vous avez besoin d'une classe qui implémente l' interface Comparator , y compris sa méthode de comparaison . Les deux méthodes indiquent comment comparer des objets d'un type donné. Ceci est essentiel lors du tri, car l’algorithme de tri doit comprendre quel principe utiliser pour comparer les éléments. Cela se fait principalement en implémentant Comparable directement dans la classe que vous souhaitez trier. L’utilisation de Comparator est moins courante. Supposons que vous utilisiez une classe d’une bibliothèque et qu’elle n’implémente pas Comparable , mais que vous deviez trier une collection de ses objets. Puisque vous ne pouvez pas modifier le code de cette classe (sauf en l'étendant), vous pouvez écrire une implémentation de Comparator qui indique comment comparer les objets de la classe. Et encore un exemple. Si vous devez trier des objets du même type de différentes manières, vous pouvez écrire plusieurs implémentations de Comparator à utiliser dans différentes situations. En règle générale, de nombreuses classes prêtes à l'emploi, par exemple String , implémentent déjà l' interface Comparable . Cela signifie que vous n'avez pas à vous soucier de la manière de comparer ces classes. Vous pouvez simplement continuer et les utiliser. La première et la plus évidente consiste à utiliser la classe TreeSet ou TreeMap . Ces classes stockent les éléments dans un ordre trié en fonction du comparateur implémenté par les éléments de classe. N'oubliez pas que TreeMap trie les clés, pas les valeurs. Si vous utilisez Comparator au lieu de Comparable , vous devez alors transmettre un objet Comparator au constructeur de la collection lorsque vous la créez :
TreeSet treeSet = new TreeSet(customComparator);
Mais que se passe-t-il si vous avez un autre type de collection ? Comment le trier ? Dans ce cas, la deuxième méthode de la classe utilitaire Collections — la méthode sort() — convient. La méthode est statique, il vous suffit donc d'ajouter le nom de la classe puis de transmettre la liste à trier. Par exemple:
Collections.sort(someList);
Si vous utilisez une implémentation de Comparator plutôt que de Comparable , vous devez la transmettre comme deuxième argument :
Collections.sort(someList, customComparator);
Cette opération va changer l'ordre interne des éléments dans la liste passée : la liste sera triée à l'aide du comparateur. Notez que la liste transmise doit être mutable, sinon la méthode échouera et lancera une UnsupportedOperationException . Une troisième option consiste à utiliser la méthode sorted de la classe Stream , qui trie les éléments de la collection. Si nous utilisons Comparable :
someList = someList.stream().sorted().collect(Collectors.toList());
Si nous utilisons Comparator :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
La quatrième méthode consiste à implémenter manuellement un algorithme de tri, par exemple un tri à bulles
ou un tri par fusion
.
Classe d'objet. est égal à() et hashCode()
94. Donnez une brève description de la classe Object en Java.
Dans la deuxième partie de la revue, nous avons déjà évoqué les méthodes de la classe Object . Ici, je vous rappelle que la classe Object est un ancêtre de chaque classe en Java. Il dispose de 11 méthodes, qui sont à leur tour héritées par toutes les classes.
95. À quoi servent equals() et hashCode() en Java ?
hashCode() est une méthode de la classe Object héritée par toutes les classes. Son travail consiste à générer un nombre qui représente un objet spécifique. Un exemple de cette méthode en action peut être trouvé dans HashMap , où elle est appelée sur des objets clés pour obtenir le hashcode local, qui déterminera dans quel compartiment (cellule du tableau interne) la paire clé-valeur sera stockée. cette méthode est généralement utilisée dans la méthode equals() comme l’un de ses principaux moyens d’identifier des objets. equals() est une méthode de la classe Object dont le travail consiste à comparer des objets et à déterminer s'ils sont égaux. Cette méthode est utilisée partout où nous devons comparer des objets, car l'opérateur de comparaison standard == ne convient pas aux objets, car il compare uniquement les références d'objets.96. Parlez-nous du contrat entre equals() et hashCode() en Java ?
Tout d’abord, permettez-moi de dire que pour que les méthodes equals() et hashCode() fonctionnent correctement, elles doivent être correctement remplacées. Leurs nouvelles implémentations doivent suivre ces règles :- Les objets identiques pour lesquels égal renvoie vrai doivent avoir les mêmes codes de hachage.
- Les objets avec les mêmes codes de hachage ne sont pas nécessairement égaux.
GO TO FULL VERSION