Tecnicamente, não é 10
zero, se você admitir uma inicialização preguiçosa da matriz de apoio. Vejo:
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
Onde
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
Você está se referindo apenas ao objeto de array inicial de tamanho zero que é compartilhado entre todos os ArrayList
objetos inicialmente vazios . Ou seja, a capacidade de 10
é garantida preguiçosamente , otimização que está presente também no Java 7.
É certo que o contrato do construtor não é totalmente preciso. Talvez esta seja a fonte de confusão aqui.
fundo
Aqui está um e-mail de Mike Duigou
Publiquei uma versão atualizada do patch vazio de ArrayList e HashMap.
http://cr.openjdk.java.net/~mduigou/JDK-7143928/1/webrev/
Esta implementação revisada não introduz novos campos para nenhuma das classes. Para ArrayList, a alocação lenta da matriz de apoio ocorre apenas se a lista for criada no tamanho padrão. De acordo com nossa equipe de análise de desempenho, aproximadamente 85% das instâncias de ArrayList são criadas no tamanho padrão, portanto, essa otimização será válida para a grande maioria dos casos.
Para HashMap, o uso criativo é feito do campo de limite para rastrear o tamanho inicial solicitado até que a matriz de intervalo seja necessária. No lado da leitura, a caixa vazia do mapa é testada com isEmpty (). No tamanho de gravação, uma comparação de (tabela == EMPTY_TABLE) é usada para detectar a necessidade de aumentar a matriz do balde. Em readObject há um pouco mais de trabalho para tentar escolher uma capacidade inicial eficiente.
De: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-April/015585.html
getCapacity()
método ou algo parecido. (Dito isso, algo comoensureCapacity(7)
é um no-op para um ArrayList inicializado por padrão, então eu acho que realmente devemos agir como se sua capacidade inicial fosse realmente 10 ...)ArrayList
criado com o construtor no-arg em vez de passar zero para oint
construtor e se observar o tamanho do array interno de forma reflexiva ou em um depurador. No caso padrão, a matriz salta do comprimento 0 para 10 e depois para 15, 22, seguindo a taxa de crescimento de 1,5x. Passar zero como capacidade inicial resulta em crescimento de 0 a 1, 2, 3, 4, 6, 9, 13, 19 ....emptyList()
ainda consome menos memória do que váriasArrayList
instâncias vazias . É apenas menos importante agora e, portanto, não é necessário em todos os locais, especialmente em locais com maior probabilidade de adicionar elementos posteriormente. Lembre-se também de que às vezes você deseja uma lista vazia imutável e esseemptyList()
é o caminho a seguir.Em java 8, a capacidade padrão de ArrayList é 0 até que adicionemos pelo menos um objeto ao objeto ArrayList (você pode chamá-lo de inicialização lenta).
Agora a pergunta é por que essa mudança foi feita em JAVA 8?
A resposta é economizar o consumo de memória. Milhões de objetos de lista de array são criados em aplicativos Java em tempo real. O tamanho padrão de 10 objetos significa que alocamos 10 ponteiros (40 ou 80 bytes) para o array subjacente na criação e os preenchemos com nulos. Uma matriz vazia (preenchida com nulos) ocupa muita memória.
A inicialização lenta adia esse consumo de memória até o momento em que você realmente usará a lista de array.
Por favor, veja o código abaixo para obter ajuda.
O artigo Capacidade padrão de ArrayList em Java 8 explica isso em detalhes.
fonte
Se a primeira operação feita com um ArrayList é passar
addAll
uma coleção que tem mais de dez elementos, então qualquer esforço colocado na criação de um array inicial de dez elementos para conter o conteúdo do ArrayList seria jogado fora da janela. Sempre que algo é adicionado a um ArrayList, é necessário testar se o tamanho da lista resultante excederá o tamanho do armazenamento de apoio; permitir que o armazenamento de apoio inicial tenha tamanho zero em vez de dez fará com que este teste falhe uma vez extra no tempo de vida de uma lista cuja primeira operação é um "adicionar" que exigiria a criação da matriz inicial de dez itens, mas esse custo é menos do que o custo de criação de uma matriz de dez itens que nunca acaba sendo usada.Dito isso, poderia ter sido possível melhorar ainda mais o desempenho em alguns contextos se houvesse uma sobrecarga de "addAll", que especificava quantos itens (se houver) provavelmente seriam adicionados à lista após a atual, e quais poderiam use isso para influenciar seu comportamento de alocação. Em alguns casos, o código que adiciona os últimos itens a uma lista terá uma boa ideia de que a lista nunca precisará de nenhum espaço além desse. Existem muitas situações em que uma lista será preenchida uma vez e nunca mais modificada depois disso. Se no ponto o código sabe que o tamanho final de uma lista será de 170 elementos, ele terá 150 elementos e um armazenamento de apoio de tamanho 160,
fonte
addAll()
. Essa é mais uma oportunidade para melhorar a eficiência em torno do primeiro malloc.A questão é 'por quê?'.
As inspeções de perfil de memória (por exemplo ( https://www.yourkit.com/docs/java/help/inspections_mem.jsp#sparse_arrays ) mostram que arrays vazios (preenchidos com nulos) ocupam toneladas de memória.
O tamanho padrão de 10 objetos significa que alocamos 10 ponteiros (40 ou 80 bytes) para o array subjacente na criação e os preenchemos com nulos. Aplicativos Java reais criam milhões de listas de array.
A modificação introduzida remove ^ W adia este consumo de memória até o momento em que você realmente usará a lista de array.
fonte
Após a pergunta acima, eu examinei o documento ArrayList do Java 8. Eu descobri que o tamanho padrão ainda é apenas 10.
fonte
O tamanho padrão de ArrayList em JAVA 8 é ainda 10. A única alteração feita em JAVA 8 é que, se um codificador adicionar elementos menores que 10, os espaços em branco de arraylist restantes não são especificados como nulos. Dizer isso porque eu mesmo passei por essa situação e o eclipse me fez olhar para essa mudança de JAVA 8.
Você pode justificar essa mudança olhando a captura de tela abaixo. Nele você pode ver que o tamanho de ArrayList é especificado como 10 em Object [10], mas o número de elementos exibidos é apenas 7. Restos elementos de valor nulo não são exibidos aqui. Em JAVA 7 abaixo, a captura de tela é a mesma com apenas uma única mudança, que é que os elementos de valor nulo também são exibidos para os quais o codificador precisa escrever código para lidar com valores nulos se ele estiver iterando a lista completa de matrizes, enquanto em JAVA 8 essa carga é removida o chefe do codificador / desenvolvedor.
Link da captura de tela.
fonte