Jaka jest różnica między lambdą a odwołaniem do metody
Źródło: Reddit IntelliJ IDEA sugeruje zastąpienie wyrażeń lambda odniesieniami do metod. Jaka jest różnica między nimi? Okazuje się, że istnieje subtelna różnica między wyrażeniami lambda a odniesieniami do metod. Na przykład porównaj: myInstance::getStuff i () ->myInstance.getStuff() . Ogólnie rzecz biorąc, obie opcje są sobie równoważne. Ale jeśli myInstance ma wartość null, a lambda generuje wskaźnik zerowy podczas oceny lambda, wówczas odwołanie do metody zostanie wygenerowane natychmiast podczas próby dostępu do odwołania. I co? Ogólnie rzecz biorąc, jest to ważne, jeśli kod oceniający wyrażenie lambda znajduje się wewnątrz try-catch ze wskaźnikiem zerowym. Na przykład mam funkcję mayBeNull (funkcja Dostawca<T>) , która robi coś takiego:try {
doStuff(function.get().getSomeMore().getSomeMore());
} catch (NullPointerException e) {
doOtherStuff();
}
Jeśli wywołanie funkcji MightBeNull(() -> myNullVariable.getStuff()) zadziałałoby bez zgłaszania wyjątku, wówczas „odpowiednik”: MightBeNull(myNullVariable::getStuff) zgłosi wyjątek NullPointerException natychmiast po wywołaniu funkcji. To jest różnica. Notatka. Według Stackoverflow, jeśli zastąpisz lambdę odwołaniem do metody, kod bajtowy klasy będzie bardziej zwarty, co oznacza, że klasa będzie ładować się szybciej do JVM. Aby jednak odczuć taki zysk, potrzebne są tysiące niezoptymalizowanych lambd. Jednak w dużym projekcie taką liczbę można łatwo zgromadzić. W przeciwnym razie wybór między lambdą a odwołaniem do metody jest kwestią gustu i czytelności kodu. Na przykład, jeśli lambda ma kilka linii, wówczas czytelność jest zmniejszona, a kod na tym skorzysta tylko wtedy, gdy lambda zostanie umieszczona w osobnej metodzie i użyte zostanie odwołanie do niej.
5 sposobów łączenia ciągu null w Javie
Źródło: Gitconnected Po przeczytaniu tego wpisu dowiesz się więcej sposobów pracy z ciągami znaków w Javie. Java udostępnia wiele sposobów łączenia ciągów znaków, ale czasami, gdy nie zwracamy uwagi na ciągi zerowe, możemy otrzymać ciąg zerowy, czego oczywiście nie chcemy. Skorzystaj więc z moich zalecanych metod, aby uniknąć wartości null podczas łączenia String.Analiza problemu
Jeśli chcemy połączyć tablice ciągów, możemy po prostu użyć operatora +. Jednak podczas wykonywania tej czynności możemy napotkać wartości zerowe .String[] values = {"https", "://", "gist.", "github", ".com", null};
String result = "";
for (String value : values) {
result = result + value;
}
Połączenie wszystkich tych elementów prowadzi do następującego wyniku:
https://Gist.github.comnull
Chociaż znaleźliśmy problem, wynikowa wartość null jest również łączona jako ciąg znaków, co zdecydowanie nie jest tym, na co liczyliśmy. Nawet jeśli pracujemy na Javie w wersji 8 lub nowszej i używamy statycznej metody String.join() do łączenia ciągów, nadal otrzymamy wartości null .
String[] values = {"https", "://", "gist.", "github", ".com", null};
String result = String.join("", values);
Wynik jest taki sam:
https://Gist.github.comnull
Jak więc rozwiązać ten problem? Istnieje kilka rozwiązań. Aby ułatwić późniejszą demonstrację kodu, wyodrębniamy metodę, która może przekazać ciąg znaków i zwrócić ciąg inny niż null.
public String nullToString(String value) {
return value == null ? "" : value;
}
1. String.concat()
String.concat() to metoda dostępna w klasie String . Jest to bardzo wygodne w przypadku łączenia ciągów.for (String value : values) {
result = result.concat(getNonNullString(value));
}
Ponieważ wywoływana jest metoda nullToString() , w rezultacie nie powstają wartości null .
2. Kreator ciągów
Klasa StringBuilder udostępnia wiele przydatnych i wygodnych metod konstruowania ciągów. Najczęściej stosowaną wśród nich jest metoda append() , która wykorzystuje funkcję append() do łączenia ciągów znaków i jest połączona z metodą nullToString() w celu uniknięcia wartości null .String[] values = {"https", "://", "gist.", "github", ".com", null};
StringBuilder result = new StringBuilder();
for (String value : values) {
result = result.append(nullToString(value));
}
W rezultacie możesz uzyskać następujący wynik:
https://gist.github.com
3. Klasa StringJoiner (Java 8+)
Klasa StringJoiner zapewnia bardziej zaawansowaną funkcję łączenia ciągów. Może nie tylko określić ogranicznik podczas łączenia, ale także określić przedrostek i przyrostek. Podczas łączenia ciągów możemy użyć metody add() . Aby uniknąć wartości null , zostanie tu również zastosowana metoda nullToString() .String[] values = {"https", "://", "gist.", "github", ".com", null};
StringJoiner result = new StringJoiner("");
for (String value : values) {
result = result.add(nullToString(value));
}
4. Filtr strumieni (Java 8+)
Stream API to zaawansowana klasa operacji na strumieniach wprowadzona w języku Java 8, która może wykonywać standardowe operacje filtrowania, dopasowywania, przeglądania, grupowania, statystyki i inne operacje.- Filtr działania filtra może otrzymać funkcję predykatu .
- Interfejs funkcji Predicate jest taki sam, jak wprowadzony wcześniej interfejs Function .
- To jest funkcjonalny interfejs.
- Może przyjmować parametr ogólny <T> , a zwracana wartość jest typu logicznego.
- Predykat jest często używany do filtrowania danych .
String[] values = {"https", "://", "gist.", "github", ".com", null};
String result = Arrays.stream(values)
.filter(Objects::nonNull)
.collect(Collectors.joining());
GO TO FULL VERSION