1. Coleções em Java
As aulas de coleta em Java são as classes mais usadas e mais convenientes da programação Java. Como classe de contêiner, a classe de coleta pode armazenar qualquer tipo de dados e, é claro, também pode armazenar tipos especificados em combinação com genéricos (mas os genéricos são válidos apenas durante o período de compilação e serão apagados em tempo de execução). O que é armazenado na classe de coleta é apenas uma referência ao objeto, não uma referência ao próprio objeto. A capacidade da classe de coleta pode ser expandida dinamicamente durante a operação e também fornece muitos métodos convenientes, como encontrar a união e a interseção da coleção.
2. Estrutura da classe de coleção
As coleções no Java incluem várias estruturas de dados, como listas vinculadas, filas, tabelas de hash etc. Em termos da estrutura de herança de uma classe, ela pode ser dividida em duas categorias. Um é herdado da interface da coleção. Esse tipo de coleção inclui classes de coleção, como LIST, Set e Fileue. A outra classe é herdada da interface do mapa, que inclui principalmente classes de coleta relacionadas às tabelas de hash. Vamos dar uma olhada nos diagramas da estrutura de herança dessas duas categorias:
1. Lista, conjunto e fila
A linha pontilhada verde na figura representa a implementação, a linha sólida verde representa a herança entre as interfaces e a linha sólida azul representa a herança entre as classes.
(1) Lista: Usamos mais listas, incluindo ArrayList e LinkedList. A diferença entre esses dois também é muito óbvia, o que pode ser visto em seus nomes. O Arraylist subjacente é implementado por meio de matrizes, portanto, sua velocidade de acesso aleatória é relativamente rápida, mas a eficiência é relativamente baixa para casos em que são necessárias adições e deleções frequentes. Para o LinkedList, a camada subjacente é implementada por meio de listas vinculadas; portanto, a operação de adição e exclusão é mais fácil de concluir, mas a eficiência do acesso aleatório é relativamente baixo.
Vamos primeiro olhar para a eficiência de inserção de ambos:
pacote com.paddx.test.collection; importar java.util.ArrayList; importar java.util.LinkedList; public class ListTest {public static void main (string [] args) {para (int i =; i <; i ++) {} long start = system.curnteMilis (int i =; i <; i ++) {} long start = system.curnteMilis () (Int i =; i <; i ++) {} long start = system.curnteMilis () (Int i =; i <; i ++) {} long start = system.curnteMilis () (Int I =; i <; i ++) {} long start = system.curnteMilis () (Int i =; i <; i ++) {} long start = System.curnteMilis; LinkedList <Teger> (); para (int i =; i <; i ++) {linkedList.add (, i);} long end = System.currenttimemillis (); system.out.println (end - start); Arraylist <Teger> Arraylist = newList <intereger> () (); i =; i <; i ++) {ArrayList.add (, i);} System.out.println (System.currenttimemillis () - end);}}Aqui estão os resultados da execução local:
vinte e três
1227
Pode -se observar que, neste caso, a eficiência da inserção do LinkedList é muito maior que a do Arraylist, é claro que essa é uma situação relativamente extrema. Vamos comparar a eficiência do acesso aleatório entre os dois:
pacote com.paddx.test.collection; importar java.util.ArrayList; importar java.util.LinkedList; importar java.util.random; public class ListTest {public static void main (string [] args) {novo aleatoriamente aleatório (); para (int =; i) LinkedList <Teger> (); para (int i =; i <; i ++) {LinkedList.add (i);} ArrayList <Teger> ArrayList = new ArrayList <Teger> (); for (int i =; i <; i ++) {ArrayList.add (i);} long start = System.currenttimEmillis (); para (int i =; i <; i ++) {int j = aleatom.nextInt (i+); int k = linkedList.get (j);} long end = System.currenttimemillis (); system.out.println (end - start); para (int i = i <; i ++) {int J = Random.Next (INTINT (IT); ArrayList.get (J);} System.out.println (System.CurrentTimEmillis () - end);}}Aqui está o resultado da minha execução:
5277
6
É óbvio que a eficiência de acesso aleatório da Arraylist é várias ordens de magnitude maiores que o LinkedList. Através dessas duas peças de código, devemos saber mais claramente a diferença entre o LinkedList e o ArrayList e os cenários de adaptação. Quanto ao vetor, é uma versão segura para o ArrayList, enquanto a pilha corresponde à estrutura de dados da pilha. Esses dois são usados com menos frequência, então não darei um exemplo aqui.
(2) Fila: Geralmente, ela pode ser feita diretamente usando o LinkedList. Também pode ser visto no diagrama de classe acima que o LinkedList herda de Deque, portanto, a LinkList tem a função de uma fila de ponta dupla. O PriorityQueue é caracterizado por proporcionar uma prioridade para cada elemento, e elementos com alta prioridade terão prioridade da fila.
(3) Conjunto: A principal diferença entre o conjunto e a lista é que o conjunto não permite que os elementos sejam repetidos, enquanto a lista pode permitir que os elementos sejam repetidos. Para julgar a repetição dos elementos, precisamos decidir com base no método de hash do objeto e igual a método. É também por isso que geralmente substituímos o método HashCode e é igual a classes de elementos em uma coleção. Vamos dar um exemplo para ver a diferença entre o conjunto e a lista, bem como o papel do método HashCode e igual a Método:
pacote com.paddx.test.collection; importar java.util.ArrayList; importar java.util.hashset; importar java.util.set; public class SettST {public static void main (string [] novo (novo) {pessoa p1 = nova pessoa ("lxp", 10); pessoa P2 = novo (" Pessoa ("lxp", 20); ArrayList <SERSO> LIST = new ArrayList <Soper> (); list.add (p1); System.out.println ("----------"); list.add (P2); System.out.println ("------------"); list.size ()); System.out.println ("---------------"); set <SERPET> set = new HashSet <SERPS> (); set.add (p1); System.out.println ("-----------"); set.add (p2); System.out.println ("-------"); set.add (p2); size = "+set.size ());} pessoa estática Pessoa {Nome de String privado; private int Age; Public Pessoa (nome da string, int Age) {this.name = nome; this.age = Age;}@SubstridePublic boolean equals (objeto o) {System.out.Intln (" o nome de chamado (); Nome ("Nome); ! = o.getclass ()) retornar false; pessoa pessoa = (pessoa) o; retorna name.equals (pessoa.name);}@substituirpublic int hashcode () {System.out.println ("Call hashcode (), idade ="+idade); idade de retorno; Os resultados da execução do código acima são os seguintes:
------------
------------
Tamanho da lista = 3
---- Divida Linha ----
Ligue para HashCode (), idade = 10
------------
Ligue para HashCode (), idade = 10
Chamada iguals (); nome = lxp
------------
Ligue para HashCode (), idade = 20
Tamanho do conjunto = 2
A partir dos resultados, nenhuma operação adicional é realizada quando o elemento é adicionado à lista e pode ser repetido. Antes de ingressar no set, você precisa executar o método HashCode primeiro. Se o valor retornado já existir no conjunto, você precisará continuar executando o método igual. Se o resultado retornado pelo método Equals também for verdadeiro, ele prova que o elemento já existe e o novo elemento será substituído pelo elemento antigo. Se o valor de hashcode retornado for diferente, você adicionará diretamente o conjunto. Lembre -se aqui de que, para elementos em uma coleção, elementos com diferentes valores de código de hash devem ser desiguais, mas para elementos com desigual, os valores de código de hash podem ser os mesmos.
A diferença entre o hashset e o LinkedHashSet é que o último pode garantir que a ordem dos elementos inseridos no conjunto seja consistente com a ordem de saída. A diferença entre Tresset é que seu tipo é classificado no comparador e, por padrão, é organizado em ordem crescente na ordem natural dos caracteres.
(4) Iterável: A partir desta figura, você pode ver que a classe de coleta herda de Iterable. A função dessa interface é fornecer travessia de elementos, ou seja, todas as classes de coleta (exceto classes relacionadas ao mapa) fornecem funções de travessia de elementos. O Iterable contém o iterador do iterador, e seu código -fonte é o seguinte. Se você estiver familiarizado com o modo iterador, deve ser fácil de entender.
interface pública iterator <e> {boolean hasNext (); e next (); void remove ();}2. Mapa:
A maior vantagem da coleção do tipo de mapa é que sua eficiência de pesquisa é relativamente alta e a complexidade do tempo de O (1) pode ser alcançada idealmente. O mapa mais usado é o hashmap. A diferença entre LinkedHashmap e Hashmap é que o primeiro pode garantir que a ordem dos elementos inseridos no conjunto seja consistente com a ordem de saída. A diferença entre esses dois e o TREEMAP é que o TREEMAP é classificado de acordo com os valores -chave. Obviamente, sua implementação subjacente também tem diferenças essenciais. Por exemplo, a camada subjacente do hashmap é uma tabela de hash, enquanto a camada subjacente de Treemap é uma árvore. Agora vamos ver a diferença entre Treemap e LinkedHashmap:
pacote com.paddx.test.collection; importar java.util.iterator; importar java.util.LinkedHashMap; importar java.util.map; importar java.util.treemap; public class Maptest {public static void main (string [], <) (string; LinkedMap = new LinkedHashMap <String, String> (); Treemap.put ("B", Null); Treemap.put ("C", NULL); Treemap.put ("A", NULL); para (iterator <strator> iter = Treemap.KeySet (). Iterator (); iter.hasnext ();) {System.out.println ("Treemap ="+iter.Next ());} System.out.prin tln ("---------- 分割线 ---------"); LinkedMap.put ("B", NULL); LinkedMap.put ("C", NULL); LinkedMap.put ("A", NULL); para (Iterator <string> iter = linkedmap.keyset (). Iterator (); iter.hasnext ();) {system.out.println ("linkedhashmap ="+iter.next ());}}} Execute o código acima e o resultado da execução é o seguinte:
Treemap = a
Treemap = b
Treemap = c
---------------------------
LinkedHashMap = b
LinkedHashMap = c
LinkedHashmap = a
A partir dos resultados em execução, é óbvio que a diferença entre Treemap e LinkedHashmap é vista claramente. O primeiro é emitido por classificação de strings, enquanto o último é emitido por ordem de inserção. Os leitores cuidadosos podem descobrir que a diferença entre Hashmap e TreeMap é consistente com as diferenças mencionadas anteriormente entre hashset e TreeSet. Ao conduzir a análise do código -fonte no futuro, podemos ver que o hashset e a árvore são essencialmente implementados através do HashMap e Treemap, respectivamente, de modo que suas diferenças são naturalmente as mesmas. A hashtable raramente é usada agora. A principal diferença do hashmap é que a hashtable é segura por threads, mas devido à sua baixa eficiência, o hashmap é geralmente usado. Em um ambiente multithread, o CurrentHashmap é geralmente usado.
3. Resumo
Este artigo apresenta apenas a estrutura de coleção Java e seu relacionamento de herança como um todo. Além das classes acima, as coleções também fornecem duas classes de ferramentas: coleções e matrizes. Além disso, a classificação na coleção está intimamente relacionada a comparável e comparador. Em um artigo subsequente, o código-fonte da implementação de classe acima mencionado no JDK será analisado em detalhes.