Próbuję analizować ciągi (niektóre mogą być bardzo długie, akapity) na podstawie białych znaków (spacje, klawisze powrotu, tabulatory). Obecnie używasz String.split("\\s++"). W poprzednim projekcie, który aktualizujemy, po prostu użyliśmy StringTokenizer. Używanie String.split("\\s++") działa dobrze we wszystkich naszych testach i ze wszystkimi naszymi beta testerami.

W chwili, gdy udostępnimy go rozszerzonym użytkownikom, będzie działał przez chwilę, aż pochłonie wszystkie zasoby serwera. Z tego, co zbadałem, wydaje się, że jest to katastrofalne cofanie się. Otrzymujemy błędy takie jak:

    ....was in progress with java.base@11.0.5/java.util.regex.Pattern$GroupHead.match(Pattern.java:4804)
    java.base@11.0.5/java.util.regex.Pattern$Start.match(Pattern.java:3619)
    java.base@11.0.5/java.util.regex.Matcher.search(Matcher.java:1729)
    java.base@11.0.5/java.util.regex.Matcher.find(Matcher.java:746)
    java.base@11.0.5/java.util.regex.Pattern.split(Pattern.java:1264)
    java.base@11.0.5/java.lang.String.split(String.java:2317)

Użytkownicy mogą wpisać szalony tekst. Jaka jest najlepsza opcja analizowania ciągów, które mogą mieć od 10 do 1000 znaków? Jestem przy ścianie z cegły. Próbowałem różnych wzorców (regex nie jest moim najsilniejszym obszarem) przez ostatnie 4 dni bez długoterminowego sukcesu.

0
Javangelist 19 grudzień 2019, 22:11
Czy możesz podać kroki do odtworzenia? Próbowałem str.split("\\s++"), gdzie str był ciągiem 16 000 znaków, ale zakończyło się w zasadzie natychmiast.
 – 
that other guy
19 grudzień 2019, 22:21
Dlaczego używasz \\s++? Powinno to nie spełniać twoich kryteriów z mojego zrozumienia. Jestem w 99% pewien, że faktycznie potrzebujesz \s+ w oparciu o moją ograniczoną wiedzę na temat interpolacji/unikania ciągów Java.
 – 
MonkeyZeus
19 grudzień 2019, 22:21
++ to zaborcza wersja zachłannego kwantyfikatora +
 – 
that other guy
19 grudzień 2019, 22:22
\s++ nie może powodować cofania się, więc problem nie dotyczy CB.
 – 
Wiktor Stribiżew
20 grudzień 2019, 01:10

1 odpowiedź

Prostym rozwiązaniem, jeśli nie ufasz wyrażeniu regularnemu, jest użycie rozwiązania nie opartego na wyrażeniu regularnym, takiego jak Apache Commons StringUtils # split. Alternatywnie, całkiem łatwo jest samemu napisać.

Pamiętaj, że różnica między używaniem StringTokenizera a funkcją dzielenia polega na tym, że tokenizer jest leniwy. Jeśli pobierałeś tylko podzbiór wyników podziału, możesz zużywać więcej pamięci podczas podziału. Spodziewałbym się tylko, że będzie to problem z dużymi strunami.

1
Deadron 19 grudzień 2019, 22:47