89. Qual a diferença entre ArrayList e LinkedList?
Esta é uma das perguntas mais populares junto com a pergunta sobre a estrutura interna do HashMap . Nenhuma entrevista está completa sem ele e, portanto, a resposta deve “rebater nos seus dentes”. Além do óbvio - nomes diferentes - eles diferem na estrutura interna. Anteriormente, examinamos a estrutura interna de ArrayList e LinkedList , portanto não entrarei em detalhes de sua implementação. Deixe-me lembrá-lo de que ArrayList é implementado com base em um array interno, que é aumentado conforme necessário de acordo com a fórmula:<размерТекущегоМассива> * 3 / 2 + 1
Ao mesmo tempo, LinkedList é implementado com base em uma lista duplamente vinculada interna, ou seja, cada elemento possui um link para o anterior e o próximo, excluindo valores que são o início/fim da lista. As pessoas gostam de fazer esta pergunta no formato: “Qual é melhor - ArrayList ou LinkedList ?”, na esperança de pegar você. Afinal, se você apontar uma delas como resposta, será a resposta errada. Em vez disso, você deve esclarecer de que situação específica está falando - acesso ao índice ou inserção no meio de uma lista. Dependendo da resposta, você poderá explicar sua escolha. Descrevi anteriormente como ArrayList e LinkedList funcionam em uma situação ou outra. Vamos resumir isso colocando-os na mesma página para comparação: Adicionando um elemento (add)
-
Добавление нового element без указания индекса How местоположения будет происходить автоматически в конец обоих списков. В LinkedList новый элемент станет новым хвостом (происходит только перезаписывание пары ссылок — алгоритмическая сложность O(1)).
В ArrayList будет добавлен новый элемент в последнюю пустую ячейку массива — O(1).
-
Добавление element по индексу How правило подразумевает вставку примерно в середину списка. В LinkedList сперва будет вестись поиск нужного места с помощью перебора элементов с “хвоста” и “головы” — O(n/2), а после — вставка значения путем переопределения ссылок элементов, между которыми вставляется новый — O(1). Суммарная алгоритмическая сложность данного действия будет O(n/2).
ArrayList в данной ситуации по индексу находит элемент — O(1), и все элементы справа (включая элемент, который уже хранится по данному индексу) двигаются на одну единицу вправо (при этом возможно понадобится создание нового списка и копирование элементов в него) — O(n/2). Суммарная сложность — O(n/2). -
Добавление element в начало списка в LinkedList будет ситуация схожая с добавлением в конец: новый элемент станет новой “головой” — O(1), в то же время когда ArrayList-у нужно будет двигать все элементы вправо — O(n).
90. Qual a diferença entre ArrayList e HashSet?
Se ArrayList e LinkedList pudessem ser comparados em termos de operações - o que é melhor - então não seria tão fácil comparar ArrayList com HashSet , porque essas são coleções completamente diferentes. Você pode comparar um prato doce com outro, mas funcionará com um prato de carne - eles são muito diferentes. Porém, tentarei dar algumas diferenças entre eles:-
ArrayList implementa a interface List , enquanto HashSet implementa a interface Set ;
-
Em ArrayList, o acesso é possível pelo índice do elemento: a operação get tem uma complexidade algorítmica de O(1) , e em HashSet o elemento requerido só pode ser obtido por força bruta, e isso é de O(1) a O(n) ;
-
ArrayList permite elementos duplicados. Em um HashSet, todos os elementos são únicos: adicionar um elemento a um HashSet cujo análogo já esteja presente na coleção não funcionará (as duplicatas são verificadas usando hashcode, daí o nome desta coleção);
-
ArrayList é implementado usando um array interno e HashSet é implementado usando um HashMap interno ;
-
Um ArrayList mantém a ordem de inserção dos elementos, enquanto um HashSet é um conjunto não ordenado e não mantém a ordem dos elementos;
-
ArrayList permite qualquer número de valores vazios (nulos), apenas um valor nulo pode ser inserido em um HashSet (afinal, a unicidade dos elementos).
91. Por que existe tanta variedade de implementações de array dinâmico em Java?
Bem, esta é mais uma questão filosófica. Bem, por que eles criam tantas novas tecnologias diferentes? Para o conforto. Na verdade, é o mesmo com um grande número de implementações de array dinâmico. Nenhum deles pode ser considerado o melhor ou ideal. Cada um tem uma vantagem em alguma situação específica. E a nossa tarefa é conhecer as suas diferenças, os seus pontos fortes/fracos: para podermos utilizar o mais adequado na situação certa.92. Por que existe tanta variedade de implementações de armazenamento de valores-chave em Java?
Aqui a situação é a mesma das implementações de array dinâmico. Não existe ninguém melhor: cada um tem pontos fortes e fracos. E nós, é claro, devemos aproveitar ao máximo os nossos pontos fortes. Exemplo: o pacote concorrente, que contém muitas tecnologias multithread, possui suas próprias coleções Concurrent . O mesmo ConcurrentHashMap tem uma vantagem na segurança do trabalho multithread com dados em comparação com um HashMap normal , mas em um ambiente não multithread ele perde velocidade. Pois bem, implementações, que não são as mais fortes em nenhuma situação, estão gradativamente deixando de ser utilizadas. Exemplo: Hashtable foi originalmente planejado para ser um HashMap thread-safe , mas ConcurrentHashMap o superou em um ambiente multithread e Hashtable acabou sendo esquecido e não é mais usado.93. Como ordenar uma coleção de elementos?
A primeira coisa a dizer é que a classe do elemento da coleção deve implementar a interface Comparable e seu método compareTo . Ou você precisa de uma classe que implemente o Comaprator com seu método comparador . Você pode ler mais sobre eles neste post . Ambos os métodos especificam como os objetos de um determinado tipo devem ser comparados. Ao classificar, isso é extremamente importante, porque você precisa entender o princípio pelo qual os elementos podem ser comparados. A principal forma de fazer isso é implementar Comparable , implementado diretamente na classe que você deseja ordenar. Ao mesmo tempo, o uso do Comparador é menos comum. Digamos que você esteja usando uma classe de alguma biblioteca que não possui uma implementação Comparable , mas precisará classificá-la de alguma forma. Sem poder alterar o código desta classe (exceto estendendo-o), você pode escrever uma implementação de Comparator , na qual você indica em qual princípio deseja comparar objetos desta classe. E mais um exemplo. Digamos que você precise de princípios diferentes para classificar objetos do mesmo tipo, então você escreve vários Comparadores que usa em situações diferentes. Como regra, muitas classes prontas para uso já implementam a interface Comparable - a mesma String . Na verdade, ao usá-los, você não precisa se preocupar em como compará-los. Você apenas os pega e usa. A primeira e mais óbvia forma é utilizar uma coleção do tipo TreeSet ou TreeMap , que armazena os elementos em ordem já ordenada de acordo com o comparador de classe do elemento. Lembre-se de que TreeMap classifica chaves, mas não valores. Se você usar a implementação Comparator em vez de Comparable , precisará passar seu objeto para o construtor da coleção na criação:TreeSet treeSet = new TreeSet(customComparator);
Mas e se você tiver um tipo diferente de coleção? Como resolver isso? Nesse caso, o segundo método da classe de utilitário Collections é adequado - o método sort() . É estático, então tudo que você precisa é o nome da classe e um método para o qual a lista necessária é passada. Por exemplo:
Collections.sort(someList);
Se você não estiver usando Comparable , mas sim uma implementação de Comparator , você precisa passá-lo como segundo parâmetro:
Collections.sort(someList, customComparator);
Como resultado, a ordem interna dos elementos da lista passada mudará: ela será classificada de acordo com o comparador de elementos. Observo que a lista de elementos transferida deve ser mutável, ou seja, mutável, caso contrário o método não funcionará e uma UnsupportedOperationException será lançada . Como terceira forma, você pode usar a operação Stream sort , que classifica os elementos da coleção se a implementação Comparable for usada :
someList = someList.stream().sorted().collect(Collectors.toList());
se Comparador :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
Você pode ler mais sobre o Stream neste artigo . O quarto método é implementar manualmente a classificação, como classificação por bolha ou classificação por mesclagem .
ClassObject. Igual e HashCode
94. Dê uma breve descrição do objeto de classe em Java
Na segunda parte da análise já falamos sobre os métodos da classe Object , e vou lembrar que a classe Object é a progenitora de todas as classes em Java. Possui 11 métodos, que, respectivamente, são herdados por todas as classes. Informações sobre todos os 11 métodos podem ser encontradas na segunda parte da discussão.95. Para que servem Equals e HashCode em Java?
hashCode() é um método da classe Object que é herdado por todas as classes. Sua tarefa é gerar algum número que represente um objeto específico. Um exemplo de utilização deste método é seu uso em um HashMap em um objeto chave para determinar ainda mais o hashcode local, que determinará a célula do array interno (bucket) na qual o par será armazenado. Falamos detalhadamente sobre o trabalho do HashMap na parte 9 da análise , então não vamos nos alongar muito sobre isso. Além disso, via de regra, este método é usado no método equals() como uma de suas principais ferramentas para determinar a identidade de objetos. equals() é um método da classe Object cuja função é comparar objetos e determinar se eles são iguais ou não. Este método é usado em todos os lugares onde precisamos comparar objetos, porque a comparação usual usando == não é adequada para objetos, porque compara apenas links para eles.96. Conte-nos sobre o contrato entre Equals e HashCode em Java?
A primeira coisa que direi é que para que os métodos equals() e hashCode() funcionem corretamente , eles precisam ser substituídos corretamente. Depois disso eles deverão seguir as regras:- objetos idênticos para os quais a comparação via igual retorna verdadeiro devem ter códigos hash idênticos;
- objetos com os mesmos códigos hash podem nem sempre ser iguais.
GO TO FULL VERSION