2010-05-21 10 views
5

Chcę ustalić, czy ciąg jest nazwa miesiąca i chcę to zrobić stosunkowo szybko. Funkcja, która jest obecnie zatrzymany w moim mózgu jest coś takiego:Czy istnieje szybszy sposób, aby dopasować dowolny ciąg do nazwy miesiąca w Javie

boolean isaMonth(String str) { 
    String[] months = DateFormatSymbols.getInstance().getMonths(); 
    String[] shortMonths = DateFormatSymbols.getInstance().getShortMonths(); 
    int i; 

    for(i = 0; i<months.length(); ++i;) { 
     if(months[i].equals(str)) return true; 
     if(shortMonths[i].equals(str) return true; 
    } 
    return false; 
} 

Jednak będę przetwarzania dużo tekstu, przeszedł jeden ciąg w czasie do tej funkcji, a większość czasu będę uzyskiwanie najgorszy przypadek przechodzenia przez całą pętlę i zwracania fałszu.

widziałam jeszcze jedno pytanie, że mówił o dopasowanie wyrażenia regularnego do nazwy miesiąc i rok, które mogą być dostosowane do tej sytuacji. Czy Regex będzie szybszy? Czy istnieje inne rozwiązanie, które może być szybsze?

+0

na początek, można przenieść/make miesięcy, shortMonths statycznych zmiennych składowych (przydzielić tylko raz) .. –

+0

wyrażeniem regularnym powinna być szybka. Specjalnie wykonana maszyna stanowa szybciej. – SyntaxT3rr0r

Odpowiedz

3

Dlaczego nie przechowywać nazwy miesiąca w HashSet? To da ci stałe sprawdzanie czasu zamiast liniowego wyszukiwania czasu, które otrzymujesz z pętli.

import java.util.HashSet; 
import java.util.Collections; 
import java.text.DateFormatSymbols; 

class Test { 
    public static void main(String[] args) { 

    HashSet<String> months = new HashSet<String>(24); 

    Collections.addAll(months, DateFormatSymbols.getInstance().getMonths()); 
    Collections.addAll(months, DateFormatSymbols.getInstance().getShortMonths()); 

    System.out.println(months.contains(args[0])); 

    } 
} 
+2

Co powiesz na 'Collections.addAll (miesiące, DateFormatSymbols.getInstance(). GetMonths())'? – msandiford

+0

Dobra rozmowa, zmienił kod – dbyrne

+0

Ta odpowiedź doprowadziła mnie do właściwego kierunku. Podobają mi się też niektóre z tego, co Kevin Day mówi kilka odpowiedzi, i postaram się włączyć do tego trochę później. – jonc

1

Scalanie miesięcy i shortMonths w pojedynczym posortowanej tablicy i zrobić binarne wyszukiwania na tablicy. Lub połączyć je w Set (HashSet) i użyć zawiera. Zmień nazwy wszystkich miesięcy na małe i wykonaj to samo z wartością wyszukiwania, jeśli chcesz uwzględnić wielkość liter.

Jeśli chcesz być w stanie odzyskać numer miesiąca, łączyć je wszystkie na mapie (HashMap) z wartością jest liczba miesięcy.

1

HashSet jest dobrym rozwiązaniem ogólnego przeznaczenia - ale myślę, że można to zrobić lepiej. Spójrz na pierwszą literę miesięcy - jfmasond - jeśli wcześniej je przefiltrujesz, i tylko sprawdzisz, czy program HashSet przejdzie, zajmie się ogromną liczbą twoich "zwrotnych fałszywych" scenariuszy.

Można to ustawić kilka sposobów - jeden bardzo prosty sposób, aby to zrobić jest użycie instrukcji switch, chociaż tabeli odnośników byłoby szybciej. Zauważ także, że wystarczy sprawdzić, czy pierwszy znak znajduje się pomiędzy a a s, więc tablica przeglądowa nie musi mieć pełnego obszaru kodu Unicode (lub UTF-8 zależnie od wymagań).

Aby to jeszcze bardziej skuteczne, można skonstruować tabelę przeglądową więc zawiera on 2 pierwsze znaki każdego miesiąca - uzyskany tabeli odnośników nie jest zbyt duży, a to drastycznie zmniejszyć liczbę wyrazów, które trzeba być sprawdzone przed hashsetem.

PS - zanim zrobisz cokolwiek z tego, należy zrobić kilka profili i upewnij się, że jest to obszar kodu, który w rzeczywistości jest wąskim gardłem.

+0

Przyjemne myśli o tabeli odnośników. Cały projekt nie całkiem się razem jeszcze chociaż, więc będę trzymać się na tabeli przeglądowej, dopóki mogę zrobić trochę lepiej profilowania – jonc

+0

zasadzie swój opisywaniu tworzenia własnych bardzo specyficzne stan maszyny (co skomentował PO przed zauważając swoje odpowiedź). W Javie starannie skonstruowana instrukcja switch * będzie szybsza niż przeglądanie tabeli: w zasadzie chcesz, aby instrukcja switch stała się kodem * tableswitch * JVM (a nie * lookupswitch *, który jest wolniejszy). Robiąc to, unikasz tabeli odnośników i dzięki temu będziesz szybszy (mniej często unieważniasz pamięć podręczną itp.).Teraz oczywiście wątpię, że OP naprawdę potrzebuje tego rodzaju optymalizacji w jego przypadku. – SyntaxT3rr0r

+0

@spycharka - dobra informacja - Nie zrobiłem wystarczająco dużo spelunkingu w bajtowym kodzie Java, ale twój opis ma sens. Interesuje mnie to, co powoduje, że interpretator tableswitch vs lookupswitch jest interpretowany - będę to wyglądał. –

Powiązane problemy