lógica de programação Java (27) - Análise de embalagem (in)

Esta secção continua a investigar a embalagem, apresenta a classe Integer, sob Classes de caracteres seção, longo e Integer semelhante, ele não é mais uma apresentação separada, outras classes básicas foram introduzidos ao longo, não repeti-los.

O que um simples inteiro para apresentá-lo? Tem algumas operações binárias, olhamos para, além disso, nós também analisar a sua valueOf alcançado.

Por que devemos nos preocupar com o código que implementa-lo? Na maioria dos casos, não se importa, vamos ser capazes de usá-lo, nós, principalmente para aprender, especialmente onde a operação binária, é a base do computador binário, mas o código é muitas vezes obscuro, nós queremos que eles têm um mais para limpar uma compreensão profunda.

Vamos olhar pouco flip.

aleta bit

uso

Integer tem dois métodos estáticos que podem ser capotou pouco:

int public static reversa (int i) 
reverseBytes int public static (int i)

Bit aleta é um int como binário, bit por bit para a direita da esquerda permutáveis, inverso é pouco permutáveis, reverseBytes é intercambiável por byte. Vamos olhar um exemplo:

Copie o código
int a = 0x12345678; 
System.out.printlnl (Integer.toBinaryString (a)); 

int r = Integer.reverse (a); 
System.out.printlnl (Integer.toBinaryString (r)); 

int RB = Integer.reverseBytes (a); 
System.out.printlnl (Integer.toHexString (Rb));
Copie o código

 a é um número inteiro, hexadecimal atribuído, a série binária que é emitido em primeiro lugar, em seguida, o reverso produz um binário, reverseBytes hexadecimais saída final, como saída:

10010001101000101011001111000 
11110011010100010110001001000 
78563412

reverseBytes é invertido byte, uma representação hexadecimal de 78 bytes, é 12, então o resultado é 78563412 fácil de entender.

aleta binário à primeira vista é errado, porque a saída não é 32, 0:00 saída anterior ignorado, enchemos 32 Look:

00010010001101000101011001111000 
00011110011010100010110001001000

Os resultados à direita.

Estes dois métodos são como consegui-lo?

reverseBytes

Olhe código reverseBytes:

Copie o código
reverseBytes int public static (int i) { 
    return ((i >>> 24)) | 
           ((i >> 8) & 0xFF00) | 
           ((i << 8) & 0xFF0000) | 
           ((i << 24)); 
}
Copie o código

Parâmetro i é igual a 0x12345678, por exemplo, analisamos o processo de implementação:

i >>> 24 deslocamento para a direita sem sinal, o byte mais elevado moveu-se para o bit mais baixo, o resultado é 0x00000012.

(I >> 8) & 0xFF00, movido para a esquerda do segundo byte para a direita da segunda, i >> 8 resultado 0x00123456, em seguida, & 0xFF00, está reservada para a direita do segundo byte, o resultado é 0x00003400.

(I << 8) & 0xFF0000, mudou-se para o lado direito do segundo byte do segundo esquerda, i << 8 resultado 0x34567800, em seguida, & 0xFF0000, está reservada para o direito do terceiro byte, o resultado é 0x00560000.

i << 24, o resultado é 0x78000000, o mais à esquerda e mais à direita bytes movido.

Os quatro resultados, em seguida, ou operações |, o resultado é 0x78563412, por isso, esquerda, direita e e ou operações, para atingir o objectivo de bytes invertida.

marcha ré

Nós olhamos para o código inverso:

Copie o código
int public static reversa (int i) { 
    // HD, Figura 7-1 
    i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555; 
    i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333; 
    i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f; 
    i = (i << 24) | ((i & 0xff00) << 8) | 
        ((i >>> 8) & 0xff00) | (i >>> 24); 
    voltar i; 
}
Copie o código

Embora esse código é muito curto, mas muito obscuro, no final o que isso significa?

A primeira linha é um comentário, "HD, Figura 7-1", O que significa? HD é representado por um livro chamado Hacker Delight, HD sua sigla, Figura 7-1 é um diagrama para 7-1 livro, o livro, o conteúdo como mostrado abaixo:

Como pode ser visto, de número inteiro em código inversa é uma cópia do livro de código na figura 1/7, o código interpretado na figura também mostra, que traduzi-lo.

A ideia básica da aleta aplicação pouco eficiente, pouco permuta única adjacente em primeiro lugar, e, em seguida, como um grupo de dois, em seguida, a troca de bits adjacentes, seguidos por um grupo de quatro comutação, em seguida, oito, dezasseis, dezasseis após o bit é completa. Esta ideia aplica-se não só para binário, decimal, também é aplicável, para facilitar a compreensão, olhamos para exemplos decimais, tais como digital flip 12345678,

A primeira rodada, a única trocados digitais adjacentes, o resultado é:

21 43 65 87

Segunda rodada, um conjunto de dois números para a troca de lado, o resultado é:

43 21 87 65

A terceira ronda, um grupo de quatro números para a troca de lado, o resultado é:

8765 4321

Virar concluída.

Para decimal, a eficiência não é alta, mas para binário, o produto é eficiente porque uma pluralidade de bits binários adjacentes pode ser trocado em uma instrução.

Esta linha é adjacente a um único intercâmbio:

x = (x & 0x55555555) << 1 | (X & 0xAAAAAAAA) >>> 1;

5 é 0101,0x55555555 representação binária binário é:

01010101010101010101010101010101

x & 0x55555555 é levar o bit ímpar de x.

Um binário é 1010,0xAAAAAAAA representação binária é:

10101010101010101010101010101010

x & 0xAAAAAAAA é tomada pouco x mesmo.

(X & 0x55555555) << 1 | (X & 0xAAAAAAAA) >>> 1;

X é representado pelo pouco estranho aos pedaços, até mesmo para a esquerda para a direita, então | fusão, atingir o objectivo de bits adjacentes intercambiáveis. Este código pode ser optimizado para ter um pequeno, apenas uma constante 0x55555555, e, em seguida, a segunda metade da primeira operação de deslocamento, torna-se:

(I & 0x55555555) << 1 | (I >>> 1) & 0x55555555;

Da mesma forma, o código seguinte é de dois bits num grupo de bits adjacentes são intercambiáveis:

i = (i & 0x33333333) << 2 | (I & 0xCCCCCCCC) >>> 2;

3 é 0011,0x33333333 representação binária binário é:

00110011001100110011001100110011 

x x & 0x33333333 é tomar dois da metade inferior de um conjunto.

C é a representação binária 1100,0xCCCCCCCC binário é:

11001100110011001100110011001100

x x & 0xCCCCCCCC é participar em dois meia altura em um conjunto.

(I & 0x33333333) << 2 | (I & 0xCCCCCCCC) >>> 2;

X é representado por um conjunto de dois, a metade inferior à metade inferior do elevado deslocamento deslocada, alta, então | combinadas, alcançar o propósito de troca. Da mesma forma, a constante pode ser removido 0xCCCCCCCC, o código pode ser optimizado para:

(I & 0x33333333) << 2 | (I >>> 2) & 0x33333333;

Da mesma forma, o código seguinte é para o grupo de quatro bits, são trocados.

i = (i & 0x0f0f0f0f) << 4 | (I >>> 4) & 0x0f0f0f0f;

A unidade é ligada em octetos, que é, bytes invertida, pode ser escrita como se segue uma forma mais directa, e reverseBytes códigos substancialmente idênticos.

i = (i << 24) | ((i & 0xff00) << 8) | 
    ((i >>> 8) & 0xff00) | (i >>> 24);

Por que escrever o código invertida, para obscurecer-lo? Ou gravação não pode ser mais fácil de compreender a maneira dele? Por exemplo, para alcançar aleta, uma idéia comum é, primeiro e último de câmbio, o segundo e swap penúltima até o meio dos dois troca está completo. Se os dados não são bits binários, a idéia é boa, mas para os bits, a eficiência é relativamente baixa.

instruções da CPU e operação eficiente não pode ser um único bit, a menor unidade de dados que é tipicamente operação de 32 bits (máquinas de 32 bits), mudança Além disso, a CPU pode ser eficientemente implementado e operações lógicas, mas mais lentamente Math.

reverter essas características é a plena utilização da CPU, realizado no câmbio paralelo e eficiente de bits adjacentes, a mesma função também pode ser alcançado em outras maneiras mais fáceis de entender, mas este é mais eficiente do que o código difícil.

mudança cíclica

uso

Integer tem dois métodos estáticos pode ser deslocada ciclicamente:

public static int rotateLeft (int i, distância int) 
public static int rotateRight (int i, distância int)

rotateLeft é Rodar para a esquerda, rotateRight é girado para a direita, a distância é o número de bits que se deslocam, chamado deslocamento cíclico, o deslocamento é relativo ao normal em termos da mudança geral, tal como à esquerda 2, a parte superior dois originais não existe certo irá preencher 0, e se for deslocada para a esquerda dois ciclos, o topo dois originais irá mover para a direita, como um anel em torno do mesmo contato. Vamos olhar um exemplo:

Copie o código
int a = 0x12345678; 
int b = Integer.rotateLeft (a, 8); 
System.out.printlnl (Integer.toHexString (b)); 

int c = Integer.rotateRight (a, 8); 
System.out.printlnl (Integer.toHexString (c))
Copie o código

b é um deslocamento para a esquerda circular resultado de 8 bits, c é um deslocamento circular direita de 8 bits resultado, a saída é:

34567812 
78.123.456

código de implementação

Código que implementa essas duas funções são:

Copie o código
public static int rotateLeft (int i, distância int) { 
    return (i << distância) | (i >>> -distância); 
} 
Public static int rotateRight (int i, int distância) { 
    return (i >>> distância) | (i << -Distância); 
}
Copie o código

Estas duas funções são intrigantes é negativo, se a distância é de 8, que i >>> - 8 O que significa? Na verdade, o menor número real de passagem à era digital direto não está de volta, mas o valor digital direta de 5, ou é um resultado direto de 0x1f digitais e de. A razão para isso é porque os cinco maiores representam 31, deslocando mais de 31 pares inteiro int é inválido.

Compreender a posição de se mover significado negativo, estamos mais propensos ao código acima, por exemplo, -8 representação binária é:

11111111111111111111111111111000

Seu menor 5 é 11000, o decimal é 24, então eu >>> - 8 é i >>> 24, i << 8 | i >>> 24 é girado para a esquerda, oito.

Código acima, eu >>> - distância é i >>> (32-distância), i << - distância é i << (32 distância).

achado bit a bit, contagem

Há outros pedaços operações inteiras, incluindo:

public static int signum (int i)

Verifique o bit de sinal, retornos positivos 1, -1, 0 retorno negativo 0

public static int lowestOneBit (int i)

Encontre o direito do número de posição do primeiro, que permanecem inalterados, o outro bit é definido como 0, o inteiro é retornado. 3 Por exemplo, binário 11, resultado binário é 01, o decimal é 1, durante 20, é 10.100 binário, o resultado é 00100, é 4 decimal.

public static int highestOneBit (int i) 

Olhando a partir do lado esquerdo do primeiro número da posição 1, que se mantêm inalterados, o outro bit é ajustado para 0, o número inteiro é devolvido.

public static int bitCount (int i)  

Encontre a representação binária do número 1. 20 Por exemplo, um número binário é 2 10100,1.

numberOfLeadingZeros int public static (int i)

Começando à esquerda é o número de nulos consecutivos. 20 Por exemplo, o binário é 10100, deixou 27 0.

numberOfTrailingZeros int public static (int i)

A extremidade direita é o número de consecutivos 0 do. 20 Por exemplo, o binário é 10100, à direita há dois zero.

Sobre realização do código, existem comentários dirigidos Delight capítulos relevantes do hacker deste livro, não vou repeti-los.

A realização valueOf

Quando mencionamos na seção anterior, criar um objeto de classe wrapper, você pode usar o método valueOf estático, você também pode usar o novo direta, mas recomenda-se usar valueOf, por quê? Nós olhamos código valueOf:

Copie o código
public static Integer valueOf (int i) { 
    assert IntegerCache.high> = 127; 
    se (i> = IntegerCache.low && i <= IntegerCache.high) 
        retornar IntegerCache.cache [i + (-IntegerCache.low)]; 
    voltar new Integer (i); 
}
Copie o código

Ele usa IntegerCache, que está dentro de um código de classe estática privada da seguinte forma:

Copie o código
classe estática privada IntegerCache { 
    static final int baixa = -128; 
    int static final; 
    cache de Integer static final []; 

    estática { 
        // alto valor pode ser configurado por propriedade 
        int H = 127; 
        Corda integerCacheHighPropValue = 
            sun.misc.VM.getSavedProperty ( "java.lang.Integer.IntegerCache.high"); 
        if (integerCacheHighPropValue! = null) { 
            int i = parseInt (integerCacheHighPropValue); 
            I = Math.max (i, 127); 
            // máxima dimensão da matriz é Integer.MAX_VALUE 
            h = Math.min (i, Integer.MAX_VALUE - (-baixa) -1); 
        } 
        Elevada = H;

        cache = new Integer [(alta - baixa) + 1]; 
        j = int baixo; 
        para (int k = 0; k <cache.length; k ++) 
            cache de [k] = new Integer (j ++); 
    } 

    IntegerCache privada () {} 
}
Copie o código

IntegerCache inteiro representando cache, em que a memória cache é uma matriz estática de variáveis ​​inteiro é inicializado no bloco estático inicializador, por padrão, um dispositivo de armazenamento 127, um total de 256 que corresponde a um número inteiro a partir de -128 a um objeto inteiro.

No código valueOf, se o valor está na faixa de cache de -128 a 127 que é o padrão, então o Integer objeto pré-adquiridos criado directamente a partir da IntegerCache, não só o alcance do cache, o objeto não é criado pelo novo.

Pelo compartilhamento de objetos comuns, você pode economizar espaço de memória, uma vez Integer é imutável, ele é armazenado em cache objetos podem ser seguramente compartilhada. Boolean / Byte / Short / Long / Character tem uma implementação similar. Este objeto comum de partilha de pensamento, é uma idéias de design comuns, em <Modo de design> isso funciona, é dado um nome, chamado Flyweight, o Inglês chamado Flyweight, ou seja, a percentagem de elementos leves.

resumo

Esta seção descreve alguns operacional bit em Integer, código de operação pouco mais obscuro, mas o desempenho é relativamente alto, vamos explicar em detalhe algum código que, se você quiser saber mais sobre, de acordo com comentários, ver Delight este livro de Hacker. Também introduzimos a realização valueOf, introduz o padrão Flyweight.

A próxima seção, vamos explorar Character

Acho que você gosta

Origin www.cnblogs.com/ivy-xu/p/12584571.html
Recomendado
Clasificación