Como Squeeze nanossegundos fora de um loop de Java
Os melhores truques são os truques mais simples. Então continue lendo para ser apresentado a um truque simples que tem sido em torno de idades - um truque que pode cortar a metade o tempo de execução de um loop de programa Java.
Imagine que pesquisar através de uma longa lista de nomes. Listagem 1 tem algum código para ilustrar a idéia.
Listagem 1: Como procurar um nome
importação java.io.File-import java.io.IOException-import classe java.util.Scanner-públicas Principal {Scanner diskFile-static int MAX_SIZE = String name 100-estático [] = new String [MAX_SIZE] vazio -public estática estática main (String [] args) throws IOException {diskFile = new Scanner (new File ( "names.txt")) - int numberOfNames = fillTheArray () - searchFor ( "Burd", numberOfNames) -} static int fillTheArray () {int i = 0-while (diskFile.hasNext () Eu lt; MAX_SIZE) {name [i ++] = diskFile.next () -} retornar i-} static void searchFor (String whatToSearchFor, int numberOfNames) {int i = 0-enquanto eu lt; numberOfNames !Nome [i] .equals (whatToSearchFor)) { i ++ -}se eu lt; numberOfNames) { System.out.println ( "Encontrado na posição" + i) -} outro { System.out.println ( "Not Found") -}}}
O código na Listagem 1 tem uma variedade de nomes. O número de entradas na matriz é numberOfNames. O código em negrito na parte inferior do perfil repetidamente verifica para uma entrada que contém os mesmos caracteres que whatToSearchFor (Neste exemplo, o nome "Burd").
O laço também verifica várias vezes para se certificar de que Eu é menos do que numberOfNames. Sem essa verificação, o funcionamento de seu programa pode desabar com um Null Pointer Exception ou um Índice de matriz fora dos limites de exceção. Aqui está o porquê:
Imagine que o names.txt arquivo contém três nomes: "Encaracolado", "Larry", e "Moe". Então Nome [0] é "Encaracolado", Nome [1] é "Larry", e Nome [2] é "Moe". Não há Nome [3] valor. (Para ser mais preciso, Nome [3] é nulo.)
O valor de numberOfNames 3. Sem é a Eu lt; numberOfNames verificar, o programa verifica !Nome [3] .equals (whatToSearchFor). Mas Nome [3] é nulo Então corra do programa explode com o Null Pointer Exception.
Imagine que o arquivo names.txt contém 100 nomes, e que MAX_SIZE é 100. Em seguida, cada entrada na nome matriz contém uma cadeia honesto-a-bondade. As entradas no nome array são Nome [0], Nome [1], e assim por diante, todo o caminho até nome [99]. Não há Nome [100] entrada.
sem a Eu lt; numberOfNames verificar, o programa verifica !Nome [100] .equals (whatToSearchFor). Mas Nome [100] não existe, então a corrida do programa morde a poeira com o Índice de matriz fora dos limites de exceção.
De uma forma ou de outra, você aparentemente tem que verificar duas coisas cada vez através do loop: Você tem que verificar se Eu lt; numberOfNames e, em seguida, verificar se !Nome [i] .equals (whatToSearchFor).
Então, a grande questão é, você pode fazer melhor? você pode verificar apenas uma condição, em vez de dois? E a resposta (como se você ainda não adivinhou) é "Sim, você pode." Este truque particular não reduzir o tempo de execução do programa aos trancos e barrancos, mas é um truque bonito, no entanto. Aqui está a idéia:
Nunca li em tantos nomes que você não tem pelo menos uma entrada matriz vazia. Em seguida, após a última entrada matriz honesto-a-bondade, adicionar mais um entry- ou seja, o nome que pretende procurar. Com este nome extra no final do array, você não tem que manter a verificação Eu lt; numberOfNames. Agora, a outra condição, !Nome [100] .equals (whatToSearchFor),deve tornar-se falsa antes você ficar sem entradas da matriz.
Listagem 2 contém algum código para ilustrar essa idéia. (As diferenças entre Listagem 2 e Listagem 1 estão marcados em negrito na Listagem 2.)
Listagem 2: Um pouco melhor Rotina de pesquisa
importação java.io.File-import java.io.IOException-import classe java.util.Scanner-públicas Principal {Scanner diskFile-static int MAX_SIZE = String name 100-estático [] = new String [MAX_SIZE] vazio -public estática estática main (String [] args) throws IOException {diskFile = new Scanner (new File ( "names.txt")) - int numberOfNames = fillTheArray () - searchFor ( "Burd", numberOfNames) -} static int fillTheArray () {int i = 0-while (diskFile.hasNext () Eu lt; MAX_SIZE - 1) {Name [i ++] = diskFile.next () -} retornar i-} searchFor static void (String whatToSearchFor, int numberOfNames) {Nome [numberOfNames] = whatToSearchFor-int i = 0-while (!Nome [i] .equals (whatToSearchFor)) {I ++ -} if (i lt; numberOfNames) {System.out.println ( "Encontrado na posição" + i) -} else {System.out.println ( "Not Found") -}}}
Na Listagem 2, o valor MAX_SIZE - 1 assegura que a matriz tem, pelo menos, uma entrada em branco. A declaração
Nome [numberOfNames] = whatToSearchFor-
coloca o nome que pretende procurar, após a última entrada da matriz honesto-a-bondade. E a condição !Nome [i] .equals (whatToSearchFor) verifica entradas da matriz até encontrar um nome do names.txt arquivo ou o nome que você colocou artificialmente após a última entrada.
Então esse é o truque. Ao adicionar uma entrada extra no final da lista, você vai de verificação de duas condições repetidamente
enquanto eu lt; numberOfNames ! Nome [i] .equals (whatToSearchFor))
de verificar apenas uma condição repetidamente:
while (! name [i] .equals (whatToSearchFor))
Aqui está um fato interessante sobre o truque descrito neste artigo: Você não precisa de um programa Java, a fim de usar esse truque. Na verdade, você não precisa sequer de um computador! O truque aplica-se a todos os tipos de situações que envolvem a pesquisa - Encontrar feito por computadores, procurando feito por robôs, e até mesmo pesquisas feitas por seres humanos.
Imagine ter uma longa fila de caixas, e dizendo a seu assistente para encontrar uma toranja em qualquer um dos primeiros cem caixas. (Amanhã, alguém vai começar a olhar a partir da caixa 101 em diante.) Você pode ter seus assistentes contar caixas, em busca, mas quem quer manter o controle de contagem de caixa, em busca? Se você já sabe onde a caixa 101 é, colocar um marcador em que a caixa e dizer ao seu assistente de pesquisa até o marcador. Melhor ainda, colocar um grapefruit falso, plástico na caixa 101 e simplesmente dizer ao seu assistente para encontrar uma toranja.
O mesmo tipo de raciocínio funciona em situações menos artificial. Uma receita para lasanha requer 50 minutos no forno. Você poderia começar o aquecimento da lasanha à 5:53 pm e olhar para o relógio a cada minuto ou assim. Quando finalmente você contou off 50 minutos, você toma a lasanha do forno.
Mas contando minutos, é irritante. Enquanto você olhar de volta para o relógio, você pode perder parte do seu comercial de TV favorito. Em vez de fazer tudo isso contando, colocar um marcador no final do processo, definindo o temporizador de cozinha para sair em 50 minutos.
Entende? Não é apenas Java. É senso comum.