Jak sprawdzić, czy nie wszystkie ciągi znaków w języku Java są spacjami?

135

Chcę sprawdzić, czy ciąg znaków Java lub tablica znaków nie składa się tylko z białych znaków, używając języka Java?

To jest bardzo podobne pytanie, poza tym, że jest to JavaScript:
Jak mogę sprawdzić, czy ciąg zawiera znaki i spacje, a nie tylko białe spacje?

EDYCJA : usunąłem trochę o znakach alfanumerycznych, więc ma to więcej sensu.

Ankur
źródło
3
Pamiętaj, że istnieje wiele różnych definicji białych znaków: spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ Którego chcesz? Albo powiesz „ma znak alfanumeryczny”, co jest zupełnie inną rzeczą. Proszę o wyjaśnienie.
Kevin Bourrillion
Przepraszamy za zamieszanie ... nie wszystkie białe spacje są kluczem - w zasadzie, jeśli mają wszystkie białe znaki, chcę je wykluczyć, ponieważ nie zawierają treści.
Ankur
2
Dzięki JDK / 11 możesz wykorzystaćString.isBlank API do tego samego.
Naman

Odpowiedzi:

226

Najkrótsze rozwiązanie, jakie przychodzi mi do głowy:

if (string.trim().length() > 0) ...

To sprawdza tylko (nie) białe znaki. Jeśli chcesz sprawdzić określone klasy postaci, musisz użyć funkcji potężnej match()z wyrażeniem regularnym, takim jak:

if (string.matches(".*\\w.*")) ...

... który sprawdza co najmniej jeden (ASCII) znak alfanumeryczny.

Carl Smotricz
źródło
9
FWIW: Spodziewałbym się, że pierwsze rozwiązanie będzie znacznie szybsze.
Stephen C
2
@Stephen C: Oczywiście! Ale jak zauważył @Uri, ze względu na niejednoznaczność pytania muszę rozwiązać dwa różne problemy :) Poza tym rzadko używam matches(): do wykonania zwykle przechowuję Patternplik w formacie final static. Opłaca się, jeśli ten sam kod jest często uruchamiany.
Carl Smotricz
3
@Andreas_D: Heh, dostałem swoje rozkazy! OP powiedział, że chce sprawdzić ciąg lub tablicę znaków, nigdy nie powiedział nic o wartościach zerowych! :) * sprawdza drobny druk w umowie * " nullnie jest ciągiem!"
Carl Smotricz
1
Ponadto „\\ w” pasuje tylko do ograniczonego podzbioru znaków innych niż białe znaki, a nie do wszystkich znaków niebędących białymi znakami, ponieważ odnosi się do „znaków słownych” zdefiniowanych jako AZ, az, 0-9 i podkreślenie.
Rob Raisch
2
Kiedyś your_string.trim () isEmpty () i nie praca dla mnie.
Neri
59

Użyłbym biblioteki Apache Commons Lang. Ma klasę o nazwie StringUtils, która jest przydatna dla wszystkich rodzajów operacji na łańcuchach. Aby sprawdzić, czy ciąg to nie wszystkie białe spacje, możesz użyć następującego:

StringUtils.isBlank(<your string>)

Oto odniesienie: StringUtils.isBlank

Chris J
źródło
8
Wolę to rozwiązanie w porównaniu z wybraną odpowiedzią. Spowoduje to również sprawdzenie ciągu == null
Richard,
To jest teraz nieprawidłowe. StringUtils.isEmptyzwróci teraz false, jeśli przekażesz „”.
James Spence
53

Nieco krótszy niż to, o czym wspomniał Carl Smotricz:

!string.trim().isEmpty();
wapno czerwone
źródło
10
Wy młodzi whippersnappers i wasze nowomodne sztuczki post-Java 1.6! Serio, przynajmniej jeden projekt w mojej firmie nadal działa na Javie 1.4 (westchnienie).
Carl Smotricz
Krótszy? Tak. Osobiście podoba mi się bardziej rozwlekły styl kodowania
Michel
9

Jeśli używasz języka Java 11 , isBlankprzyda się nowa metoda ciągów:

!s.isBlank();

Jeśli używasz języka Java 8, 9 lub 10 , możesz zbudować prosty strumień, aby sprawdzić, czy ciąg nie jest tylko białymi znakami:

!s.chars().allMatch(Character::isWhitespace));

Oprócz tego, że nie wymagają żadnych bibliotek innych firm, takich jak Apache Commons Lang, rozwiązania te mają tę zaletę, że obsługują dowolny znak odstępu, a nie tylko zwykłe ' 'spacje, jak trimsugerowałoby to rozwiązanie oparte na a w wielu innych odpowiedziach. Pełną listę wszystkich obsługiwanych typów białych znaków można znaleźć w dokumentacji Javadocs . Zwróć uwagę, że puste ciągi są również objęte w obu przypadkach.

Pyves
źródło
5
if(target.matches("\\S")) 
    // then string contains at least one non-whitespace character

Zwróć uwagę na użycie odwrotnego ukośnika cap-S, co oznacza „znak inny niż biały znak”

Założę się, że jest to najprostsze (i być może najszybsze?) Rozwiązanie.

Rob Raisch
źródło
2
Spróbujmy: String year="1995"; year.matches("\\S"); will return falsewięc to nie jest poprawne rozwiązanie. : |
Nhat Dinh
6
Nie, masz rację, chociaż nie potrafię wyjaśnić dlaczego. Zgodnie z dokumentacją Java, String.matches sprawdza, czy dany ciąg pasuje do wyrażenia regularnego. Małe eksperymenty pokazują, że nie jest to do końca dokładne, ponieważ ta funkcja wydaje się pasować TYLKO, jeśli podane wyrażenie regularne pasuje do CAŁEGO ciągu! Zatem zmiana powyższego wyrażenia regularnego („\\ S”) na „^. * \\ S. * $” Będzie działać zgodnie z oczekiwaniami, chociaż to zachowanie nie jest poprawnie udokumentowane i wydaje się znacznie różnić od każdej innej implementacji dopasowania ciągów używając wyrażeń regularnych.
Rob Raisch
4

Ta odpowiedź skupia się bardziej na uwadze bocznej „ tj. Ma co najmniej jeden znak alfanumeryczny ”. Poza tym nie dodaje zbyt wiele do innego (wcześniejszego) rozwiązania, z wyjątkiem tego, że nie szkodzi ci z NPE w przypadku, gdy String jest null.

Chcemy, falsejeśli (1) s jest nulllub (2) s jest puste lub (3) s zawiera tylko białe znaki.

public static boolean containsNonWhitespaceChar(String s) {
  return !((s == null) || "".equals(s.trim()));
}
Andreas Dolk
źródło
4

Jeśli sprawdzasz tylko białe znaki i nie przejmujesz się wartością null, możesz użyć org.apache.commons.lang.StringUtils.isWhitespace (String str),

StringUtils.isWhitespace(String str);

(Sprawdza, czy ciąg zawiera tylko białe znaki).

Jeśli chcesz również sprawdzić, czy nie ma wartości null (w tym spacji), to

StringUtils.isBlank(String str);
Bieg
źródło
isBlank (String) jest zalecany, ponieważ obsługuje również walidację wartości null!
Sachidananda Naik
2

W Javie-11 + możesz skorzystać z String.isBlankAPI, aby sprawdzić, czy dany ciąg nie składa się w całości z białych znaków -

String str1 = "    ";
System.out.println(str1.isBlank()); // made up of all whitespaces, prints true

String str2 = "    a";
System.out.println(str2.isBlank()); // prints false

Javadoc dla tego samego to:

/**
 * Returns {@code true} if the string is empty or contains only
 * {@link Character#isWhitespace(int) white space} codepoints,
 * otherwise {@code false}.
 *
 * @return {@code true} if the string is empty or contains only
 *         {@link Character#isWhitespace(int) white space} codepoints,
 *         otherwise {@code false}
 *
 * @since 11
 */
public boolean isBlank()
Naman
źródło
1

Metoda przycinania powinna działać świetnie.

http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/api/java/lang/String.html#trim ()

Zwraca kopię ciągu z pominięciem wiodących i końcowych białych znaków. Jeśli ten obiekt String reprezentuje pustą sekwencję znaków lub pierwszy i ostatni znak sekwencji znaków reprezentowanej przez ten obiekt String mają kody większe niż „\ u0020” (znak spacji), wówczas zwracane jest odwołanie do tego obiektu String.

W przeciwnym razie, jeśli w ciągu nie ma żadnego znaku o kodzie większym niż „\ u0020”, zostanie utworzony i zwrócony nowy obiekt String reprezentujący pusty ciąg.

W przeciwnym razie niech k będzie indeksem pierwszego znaku w ciągu, którego kod jest większy niż „\ u0020”, i niech m będzie indeksem ostatniego znaku w ciągu, którego kod jest większy niż „\ u0020”. Tworzony jest nowy obiekt String, reprezentujący podłańcuch tego ciągu, który zaczyna się od znaku o indeksie k i kończy się znakiem o indeksie m-to jest wynik this.substring (k, m + 1).

Ta metoda może być używana do przycinania białych znaków z początku i końca łańcucha; w rzeczywistości przycina również wszystkie znaki sterujące ASCII.

Zwraca: kopię tego ciągu z usuniętymi początkowymi i końcowymi białymi znakami lub ten ciąg, jeśli nie ma wiodących ani końcowych białych znaków. Wiodące lub końcowe białe znaki.

Możesz przyciąć, a następnie porównać z pustym ciągiem lub sprawdzić długość na 0.

Corey Ogburn
źródło
Link w odpowiedzi jest martwy - 404 | Przepraszamy, strona nie istnieje lub nie jest już dostępna .
Pang
1

Tylko porównanie wydajności na openjdk 13, Windows 10. Dla każdego z tych tekstów:

"abcd"
"    "
" \r\n\t"
" ab "
" \n\n\r\t   \n\r\t\t\t   \r\n\r\n\r\t \t\t\t\r\n\n"
"lorem ipsum dolor sit amet  consectetur adipisici elit"
"1234657891234567891324569871234567891326987132654798"

wykonał jeden z następujących testów:

// trim + empty
input.trim().isEmpty()

// simple match
input.matches("\\S")

// match with precompiled pattern
final Pattern PATTERN = Pattern.compile("\\S");
PATTERN.matcher(input).matches()

// java 11's isBlank
input.isBlank()

każdy 10.000.000 razy.

Wyniki:

METHOD    min   max   note
trim:      18   313   much slower if text not trimmed
match:   1799  2010   
pattern:  571   662   
isBlank:   60   338   faster the earlier hits the first non-whitespace character

Dość zaskakujące jest, że trym + pusty jest najszybszy. Nawet jeśli musi utworzyć przycięty tekst. Jeszcze szybsza niż prosta pętla for szukająca pojedynczego znaku bez spacji ...

EDYCJA: Im dłuższy tekst, tym więcej liczb się różni. Przycinanie długiego tekstu zajmuje więcej czasu niż zwykła pętla. Jednak wyrażenia regularne są nadal najwolniejszym rozwiązaniem.

martlin
źródło
0

Alternatywny:

boolean isWhiteSpaces( String s ) {
    return s != null && s.matches("\\s+");
 }
OscarRyz
źródło
1
\\ s * dopasuje wszystkie ciągi znaków ze spacjami lub bez. Może masz na myśli \\ s +?
Rob Raisch
0

trim () i inne wymienione wyrażenia regularne nie działają dla wszystkich typów białych znaków

tj .: znak Unicode „LINE SEPARATOR” http://www.fileformat.info/info/unicode/char/2028/index.htm

Funkcje języka Java Character.isWhitespace () obejmują wszystkie sytuacje.

Dlatego należy zastosować wspomniane już rozwiązanie StringUtils.isWhitespace (String) / lub StringUtils.isBlank (String) .

andreyro
źródło
0

Chociaż osobiście wolałbym !str.isBlank(), jak sugerowali inni (lub str -> !str.isBlank()jako predykat), bardziej nowoczesna i wydajna wersja powyższego str.trim()podejścia używałabystr.strip() - traktując null jako „białe spacje”:

if (str != null && str.strip().length() > 0) {...}

Na przykład jako predykat, do użytku ze strumieniami, np. W teście jednostkowym:

@Test
public void anyNonEmptyStrippedTest() {
    String[] strings = null;
    Predicate<String> isNonEmptyStripped = str -> str != null && str.strip().length() > 0;
    assertTrue(Optional.ofNullable(strings).map(arr -> Stream.of(arr).noneMatch(isNonEmptyStripped)).orElse(true));
    strings = new String[] { null, "", " ", "\\n", "\\t", "\\r" };
    assertTrue(Optional.ofNullable(strings).map(arr -> Stream.of(arr).anyMatch(isNonEmptyStripped)).orElse(true));
    strings = new String[] { null, "", " ", "\\n", "\\t", "\\r", "test" };
}
fozzybear
źródło