Java Collections Framework da perguntas mais frequentes da análise da entrevista

Lista de Discussão Set diferença ,, Mapa dos três?

  • List (a fim de lidar com um bom ajudante):  lojas Lista um conjunto de interfaces não é única (pode haver vários elementos fazem referência ao mesmo objeto), ordenou objetos
  • Set (prestar atenção à natureza única):  não permitem coleções duplicadas. Não haverá mais elementos se referem ao mesmo objeto.
  • Mapa (perito com chave para procurar):  Use para armazenar pares chave-valor. Mapa lhe manter e Key valor associado. Chave dois podem referenciar o mesmo objeto, mas não pode repetir-chave, normalmente do tipo String chave, mas pode ser qualquer objeto.

ArrayList e LinkedList diferença?

  • 1. É a segurança do thread garantia: ArrayList  e  LinkedList não são sincronizados, isso não é garantido para ser thread-safe;

  • 2. A estrutura de dados subjacente: Arraylist  a camada inferior utilizando  Object uma matriz ; LinkedList fundo usando um  lista duplamente ligada  estrutura de dados (como antes JDK1.6 lista encadeada circular, JDK1.7 cancelado e o duplamente ligada lista bidireccional atenção distinção lista encadeada circular circular, o abaixo descrito. !)

  • 3. Inserir e eliminar elementos Se o local afectado:  ①  ArrayList tempo utilizando uma matriz de armazenamento, de modo que o inserto e elementos de eliminação dos elementos do complexo de influenciar a posição do objecto.  Por exemplo: a aplicação add(E e) de métodos quando,  ArrayList por padrão no fim do elemento especificado adicionada a esta lista, neste caso complexidade de tempo é O (1). Mas se eu quiser inserir e elementos de exclusão no local especificado, então ( add(int index, E element) ) sobre a complexidade de tempo é O (ni). Desde quando se realiza a operação acima no primeiro conjunto após o i-ésimo elemento e i elementos (Ni) ter de realizar manipulação pouco para trás direco / para a frente de um. ②  LinkedList memória lista ligada, de modo que o add(�E e)método de inserção, a exclusão de elementos grau de complexidade de tempo de influência da posição de elemento, cerca de O (1), se você quiser especificar o local da iinserção do elemento e exclusão de palavras ( (add(int index, E element)) complexidade de tempo aproximado o(n))por causa da necessidade de para um local específico e, em seguida, inseridos.

  • 4. suporta o acesso rápido aleatório: LinkedList  não suportam eficiente acesso elemento aleatório, e  ArrayList apoio. acesso rápido para acesso aleatório rápido é através do elemento objecto é um número elemento (correspondendo ao get(int index) método).

  • pegada 5. Memória:  espaço desperdiçado ArrayList reflecte-se principalmente na lista no final da lista vai reservar alguns LinkedList capacidade de espaço, custo e espaço se reflete em cada um dos seus elementos precisam consumir mais espaço do que ArrayList (porque para armazenar o antecessor direto e imediato e dados sucessor).

 

Suplemento: RandomAccess interface

public interface RandomAccess {
}

Ver fonte descobrimos que, na verdade,  RandomAccess interface de nada está definido. Então, na minha opinião  RandomAccess a interface é apenas um Bale logotipo. Que identidade? Logo implementar essa interface com recursos de acesso aleatório.

Em  binarySearch() método, é para determinar se a lista de entrada  RamdomAccess exemplo, em caso afirmativo, chamar o indexedBinarySearch()método, se não, em seguida, chamar o iteratorBinarySearch()método

    public static <T>
    int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
    }

ArrayList Implementa  RandomAccess uma interface, mas  LinkedList não de implementação. Por quê? Eu acho que ela está relacionada com a estrutura e os dados subjacentes! ArrayList A camada inferior é uma matriz, e  LinkedList a parte inferior é uma lista ligada. Uma matriz de acesso aleatório suporte natural, complexidade de tempo é O (1), assim chamado acesso aleatório rápido. Necessidade de percorrer a lista para um local específico para acessar os elementos de um local específico, complexidade de tempo é O (n), ele não suporta acesso rápido aleatório. , ArrayList Implementos  RandomAccess a interface, como mostrado por seu acesso aleatório rápido. RandomAccess Simplesmente identifica a interface, não quer dizer que  ArrayList realize  RandomAccess a interface que tem a função de acesso rápido aleatório!

Aqui, então, resumir a seleção da lista modo de travessia:

  • Implementos  RandomAccess lista de preferência interface para circulação geral, foreach seguido,
  • Não realizado  RandomAccesslista de interface, travessia de preferência iterator (foreach para percorrer através da subjacentes iterador é implementado), o grande tamanho dos dados, não use ordinária loop

Suplemento: two-way e bidireccional lista ligada lista circular

listas duplamente ligada:  contém dois ponteiros, prev aponta um nó anterior, um ponteiro para o próximo nó seguinte.

Bidirecional lista circular:  o último ponto próximo nó cabeça, e os pontos de cabeça para o último prev nó, para formar um anel.

uploading.4e448015.gif

A diferença entre vetor e ArrayList isso? Por que ArrayList substituído Vector isso?

 

VectorTodos os métodos da classe são sincronizados. Um objeto vetorial pode ser acessado por dois fios de segurança, mas um segmento para acessar as palavras de código de Vector a gastar um monte de tempo na operação síncrona.

ArraylistNão sincronizado, recomenda-se que quando não for necessário para garantir a utilização segura do fio ArrayList.

A diferença entre HashMap e Hashtable

  1. É seguro para thread:  HashMap não é thread-safe, HashTable são thread-safe; métodos básicos HashTable internos foram synchronized modificados. (Se você quiser garantir thread-safe, então use ConcurrentHashMap isso!);
  2. Eficiência:  Porque os problemas de segurança da linha, HashMap HashTable que um pouco alta eficiência. Além disso, o HashTable foi basicamente eliminado, não é usada no código;
  3. Suporte para um valor nulo e chave nulo:  o HashMap em, como chave null, apenas uma tal chave, pode haver uma ou mais teclas correspondentes ao valor null. . Mas colocar o HashTable nas chaves, enquanto há um nulo, NullPointerException lance direta.
  4. A capacidade inicial e cada uma capacidade de tamanho de expansão tamanhos diferentes:  ① Ao criar um valor inicial, se a capacidade não estiver especificado, padrão Hashtable tamanho inicial é de 11, depois de cada expansão, a capacidade do original torna-se 2n + 1. HashMap tamanho de inicialização padrão é 16. Depois de cada expansão, a capacidade torna-se 2 vezes o original. Quando ② criar se for dada a capacidade do valor inicial, Hashtable irá direcioná-lo para usar um determinado tamanho, e HashMap irá expandir seu tamanho é uma potência de 2 (HashMap em tableSizeFor()garantias abordagem, o código fonte é dada abaixo). Que HashMap utilize sempre uma potência de 2 como o tamanho da tabela de hash, que serão introduzidos mais tarde por que é uma potência de dois.
  5. Subjacente a estrutura de dados:  JDK1.8 após HashMap fez mudanças significativas na resolução de colisão de hash, quando o comprimento da cadeia é maior que o valor limite (o padrão é 8), em uma lista de árvore vermelho-preto para reduzir o tempo de busca. Hashtable existe tal mecanismo.

Com uma capacidade inicial do construtor HashMap:

    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }
     public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

Este método assegura que o seguinte HashMap sempre utilizar uma potência de 2, tal como o tamanho da tabela de hash.

    /**
     * Returns a power of two size for the given target capacity.
     */
    static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

HashMap e HashSet diferença

Se você olhar para  HashSet o código-fonte, então você deve saber: HashSet é baseada na implementação HashMap subjacente. (Fonte HashSet muito, muito pequeno, pois, além  clone() , writeObject(), readObject()está fora do HashSet-se ter de aplicar, outros métodos são métodos em HashMap chamado directamente.

HashMap HashSet
interface de implementos Mapa Implementa a interface Set
pares chave-valor de loja Somente objetos de armazenamento
Chamada para  put()adicionar elementos ao mapa Chame o  add()método para adicionar elementos ao Set
Use HashMap chave (Key) é Hashcode calculado membro HashSet objetos para calcular o valor de código de hash, hashcode pode ser a mesma para os dois objectos, que é igual a () método para a determinação igualdade alvo,

Como verificar para duplicado HashSet

Ao aderir a um objeto HashSetquando, HashSet irá primeiro calcular o objeto hashcodevalor para determinar a posição do objeto adicionado, também serão comparados com objetos outro valor hashcode adicionadas, se não houver correspondência de hashcode, HashSet assume que o objeto não se repita. Mas se o objeto tem o mesmo valor hashcode encontrado, em seguida, ele chama o equals()método para verificar se o objeto realmente iguais hashcode mesmo. Se eles são o mesmo, HashSet não vai deixar participar de uma operação bem sucedida. (Trecho do meu livro Java iluminação "Cabeça punho java" segunda edição)

hashCode () e equals () as disposições pertinentes:

  1. Se dois objetos são iguais, também deve ser o mesmo hashcode
  2. Dois objetos são iguais, retorna verdadeiro é igual a dois métodos
  3. Hashcode dois objetos têm o mesmo valor, eles não são necessariamente iguais
  4. Em resumo, é igual substituído o método, o método deve ser coberto hashCode
  5. O hashCode comportamento padrão () é criar um valor único para objetos no heap. Se nenhum hashCode override (), em seguida, os dois objetos não são iguais classe de qualquer maneira (mesmo que esses dois objetos apontam para a mesma data).

== e é igual à diferença

  1. == duas variáveis ​​são determinados ou exemplos não são direcionados para o mesmo espaço de memória é igual ao valor de duas variáveis ​​são determinados ou exemplos aponta para o espaço de memória não é o mesmo
  2. == se refere ao endereço de memória comparando iguais () é comparado com o conteúdo da cadeia
  3. São as mesmas referências se referem == equals () refere-se aos valores são idênticos

A realização do HashMap subjacente

antes JDK1.8

JDK1.8 antes de  HashMap a parte inferior é  uma matriz e listas ligadas  utilizados em conjunto é  de hash cadeia . HashMap obtido por chave hashCode decorrido após a função de valor de processamento de hash perturbação, e em seguida por (n - 1) & hash de determinar a posição do elemento de corrente armazenado (n aqui refere-se ao comprimento da matriz), existe actualmente posição elemento, então é determinada valor de hash do elemento a ser armazenado, bem como elementos-chave são os mesmos, se as mesmas palavras, cobertura direta, não é o mesmo método para resolver conflitos através do zíper.

A função perturbação chamado refere-se ao método de hash é o HashMap. A função hash método usando é para evitar perturbação do relativamente pobre após algum método implementações hashCode () usando as palavras de função de perturbação pode reduzir colisões.

JDK método 1.8 HashMap de haxixe Fonte:

O hash JDK 1,8 JDK método de hash 1,7 em comparação com o método mais simplificado, mas o mesmo princípio.

    static final int hash(Object key) {
      int h;
      // key.hashCode():返回散列值也就是hashcode
      // ^ :按位异或
      // >>>:无符号右移,忽略符号位,空位都以0补齐
      return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
  }

Comparar o método de hash-fonte de HashMap de JDK1.7.

static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).

    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

Em comparação com o método de hash JDK1.8, o desempenho do método de hash de JDK 1.7 será um pouco fraco, porque, depois de tudo perturbado quatro vezes.

O chamado  "método zipper"  é: lista vontade e matriz combinada. Isso cria um array de lista ligada, cada célula na matriz é uma lista ligada. Se você encontrar hash de colisão, o valor será adicionado à lista de conflitos podem ser.

depois de JDK1.8

Em comparação com as versões anteriores, fez mudanças significativas após JDK1.8 na resolução de hash colisão, quando o comprimento da cadeia é maior que o valor limite (o padrão é 8), a árvore rubro-negro na lista ligada para reduzir o tempo de busca.

TreeMap, TreeSet e HashMap subjacente após JDK1.8 ter usado a árvore rubro-negro. árvore de vermelho-preto é uma árvore de busca binária, a fim de resolver o defeito, porque árvore de busca binária em alguns casos, degenerou em uma estrutura linear.

Leitura recomendada:

Por comprimento HashMap é uma potência de 2

A fim de permitir HashMap acesso eficiente, menor impacto possível, que é tentar colocar os dados é distribuído uniformemente. Também falamos sobre o topo, o valor gama Hash com o valor de -2147483648 2147483647, provavelmente somam em torno de 4 bilhões espaço mapeamento, enquanto o mapeamento de função hash foi mais uniformemente solto, aplicação geral é difícil de ocorrer colisão. Mas o problema é uma série de quatro bilhões de comprimento, a memória não está apto. Assim, o valor de hash não pode ser usado diretamente com. Além disso, o comprimento da matriz do primeiro módulo de operação antes da sua utilização, a fim de obter o restante a ser armazenado é a posição correspondente ao índice de matriz. Este índice de matriz é calculada por (n - 1) & hash"" (Matriz N representando comprimento). Isso também explica por comprimento HashMap é uma potência de dois.

Como é que este algoritmo deve projetá-lo?

Em primeiro lugar, podemos pensar em usar operação de módulo% de alcançar. No entanto, o foco aqui: "módulo (%) a operação, se o divisor é uma potência de 2 é equivalente a uma redução da sua divisor E (&) operação (isto é, de hash% comprimento de hash == & (comprimento -1) desde que o comprimento é a potência de ordem n de 2;.) "  e  a operação de bits binário &,% em relação à eficiência da operação, pode ser melhorada, o que explica por que razão comprimento HashMap é uma potência de dois.

HashMap resultados operacionais multi-threaded em problema ciclo infinito

A razão principal é que na Rehash concomitante vai resultar em uma lista encadeada circular é formado entre os elementos. No entanto, jdk 1.8 resolve esse problema, mas ainda não é recomendável o uso de HashMap em um uso multi-threaded, multi-threaded porque HashMap ainda terá outros problemas, como a perda de dados. ambiente Concurrent recomendado ConcurrentHashMap.

Para mais detalhes, consulte: https://coolshell.cn/articles/9606.html

ConcurrentHashMap e a diferença entre Hashtable

ConcurrentHashMap ea diferença Hashtable reflecte-se principalmente nas diferentes maneiras de conseguir thread-safe.

  • Subjacente a estrutura de dados:  de ConcurrentHashMap usando JDK1.7 inferior  lista de matriz segmento +  implementada, a estrutura de dados utilizado com JDK1.8 HashMap1.8 como estrutura, uma lista ligada matrizes + / vermelho e preto árvore binária. Hashtable HashMap subjacente na estrutura de dados e são semelhantes ao uso JDK1.8 anterior  matriz + cadeia  forma, a matriz é HashMap sujeito, a cadeia principal é resolver existe hash de colisão;
  • Maneira de conseguir isenta de segmentos (importante):  ①  quando o JDK1.7, ConcurrentHashMap (sub-bloqueio)  na matriz balde inteiro foi dividido segmentos (segmento), cada fecho só prender o contentor na qual parte dos dados, o acesso de vários segmentos dados de contentores de diferentes segmentos, não haveria contenção de bloqueio e melhorar a taxa de simultaneidade. JDK1.8 ter abandonado o conceito de segmento de tempo, mas gama Nó diretamente ligada estrutura de lista de dados + + árvore de vermelho-preto para implementar o controle de concorrência e sincronizados usando CAS operado. (JDK1.6 mais tarde no fechamento sincronizado para fazer um monte de otimização)  toda a aparência como HashMap otimizado e thread-safe, embora você ainda pode ver o Segmento de estrutura de dados em JDK1.8, mas simplificou a propriedade, apenas para compatível com versões anteriores; ②  Hashtable (mesmo bloqueio)  : uso sincronizado para garantir a segurança de discussão, a eficiência é muito baixa. Quando um segmento para método de sincronização de acesso, outros segmentos também pode método de sincronização de acesso, pode ser bloqueado ou entrar em um estado de votação, como a adição de elementos usando uma opção de venda, você não pode adicionar outro segmento usar elementos colocar, você não pode usar começar, a competição se tornará cada vez mais acirrada a diminuir a eficiência.

Um conjunto de estruturas de dados subjacentes quadro resumido

Coleção

1. Lista

  • ArrayList:  matriz de objeto
  • O vetor:  matriz de objeto
  • LinkedList:  lista duplamente ligada (para a lista circular antes JDK1.6, JDK1.7 cancelado ciclo)

2. Defina

  • HashSet (aleatório, único):  com base HashMap implementado usando o elemento de armazenamento subjacente para HashMap
  • LinkedHashSet:  LinkedHashSet herdado de HashSet, e o seu interior é conseguida por meio de LinkedHashMap. Algo semelhante ao que dissemos antes LinkedHashMap seu interior é a mesma implementação baseada HashMap, mas ainda um pouco de diferença
  • TreeSet (apenas por encomenda):  árvore de vermelho-preto (auto-equilíbrio tipo árvore binária)

Mapa

  • HashMap:  Antes JDK1.8 HashMap + lista pela matriz que consiste de uma matriz de HashMap é o principal, a lista é principalmente a colisão determinação de hash existe ( "zipper método" para resolver o conflito). Depois de JDK1.8 fez mudanças significativas na resolução de hash colisão, quando o comprimento da cadeia é maior que o valor limite (o padrão é 8), em uma lista de árvore vermelho-preto para reduzir o tempo de busca
  • Um LinkedHashMap:  um LinkedHashMap herdado de HashMap, de modo que ainda se baseia na estrutura subjacente é um fecho de correr de hash e uma lista ou uma matriz composta de árvore vermelho-negra. Além disso, um LinkedHashMap na base da estrutura acima, um aumento de uma lista duplamente ligado, de modo que a estrutura acima, pode ser mantido na ordem de inserção da chave. Simultaneamente pela operação da lista ligada correspondente, a ordem de acesso para alcançar a lógica associada. Detalhes podem ser vistos: "LinkedHashMap detalhada análise de código fonte (JDK1.8)"
  • Hashtable:  lista + matriz que consiste de uma matriz de HashMap é o principal, a lista é principalmente a existência de hash determinação de colisão
  • TreeMap:  árvore de vermelho-preto (auto-equilíbrio tipo árvore binária)

Como escolher o set?

De acordo com o principal conjunto de recursos para escolher, por exemplo, precisamos chave na seleção da coleção em chegar aos valores de elementos interface do mapa, necessidade de classificar a TreeMap escolha, quando ele não precisa tipo HashMap seleção, a necessidade de assegurar o fio de segurança na ConcurrentHashMap seleção. Quando nós só precisam ser armazenados valor do elemento, você selecione a coleção implementar a interface coleção, você precisa garantir que o único elemento para alcançar o conjunto ao selecionar o conjunto de interface, como TreeSet ou um HashSet, você não precisa escolher, como ArrayList ou LinkedList implementa a interface List, e depois implementá-las de acordo com ele apresenta uma coleção de interfaces para escolher.

 

 

 

 

 

 

 

 

 

 

Publicado 96 artigos originais · ganhou elogios 32 · vê 30000 +

Acho que você gosta

Origin blog.csdn.net/qq_41345773/article/details/104989982
Recomendado
Clasificación