Problem z wyrażeniem lambda

Problem z wyrażeniem lambda
DU
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 4 lata
  • Postów:143
0

Cześć,
zwracam się do Was z jednym pytaniem, dlaczego to nie działa?
Posiadam Eclipse Neon i zainstalowane jdk 1.8
W liście book przechowują obiekty, które zawierają tytuł, autora itd.
Po wprowadzeniu książki chciałbym ją wyświetlić w taki sposób:
main

Kopiuj
ArrayList<Book> book = new ArrayList<Book>();
OptionLibrary oLib = new OptionLibrary();
book = oLib.AddBook(book);
oLib.ShowBooks(book, b -> b.titleBook);//tutaj nie działa

metoda ShowBooks

Kopiuj
public void ShowBooks(ArrayList<Book> book, CheckBook verification)
	{
		for(Book fBook : book)
		{
			if(verification.canRemove(fBook))
				System.out.println(fBook);
		}
	}

CheckBook

Kopiuj
public interface CheckBook
{
	String titleBook (Book book);
	String author (Book book);
	int isbn (Book book);
	int sizeBook (Book book);
	boolean canRemove (Book book);
}

PS. uczę się lambdy, a jak się nauczę to później strumienie - to tak w razie "wu"

edytowany 2x, ostatnio: duzy
nie100sowny
Pokaż interfejs CheckBook
nie100sowny
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 dni
  • Lokalizacja:Kraków
  • Postów:402
0

Nie nie działa, ale się nie kompiluje !?!?!?!?
Może wkleisz z łaski swojej błąd?

EDIT: Mówisz kompilatorowi tak:
Wywołaj ShowBooks z listą książek i interfejsem CheckBook, który ma 5 metod ale ja Ci tutaj daję jedną (nie wiem którą - zgadnij), i ta metoda biorąc Book zwróci String tytuł.


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
edytowany 2x, ostatnio: nie100sowny
DU
Możesz mi pokazać jak to ma wyglądać? Nie mogę sobie wyobrazić tego...
DU
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 4 lata
  • Postów:143
0

No to w sumie nie kompiluje się i nie działa:

Kopiuj
Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
	The method ShowBooks(ArrayList<Book>, CheckBook) in the type OptionLibrary is not applicable for the arguments (ArrayList<Book>, (<no type> b) -> {})
	The target type of this expression must be a functional interface

	at Library.main(Library.java:10)
edytowany 2x, ostatnio: duzy
nie100sowny
Looknij EDIT: wyżej
nie100sowny
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 dni
  • Lokalizacja:Kraków
  • Postów:402
0

Lambda - to szybki sosób na zapis metody / zachowania bez deklarowania klasy implementującej interfejs np.

Jeżeli masz Interfejs z jedną metodą i ma on adnotację @FunctionalInterface to wtedy nie musisz tworzyć klasy która go implementuje, a możesz szybko przekazać lambdę

WNIOSEK: Twój interfejs CheckBook nie ma adnotacji @FunctionalInterface i ma 5 metod więc nie możesz zastąpić go lambdą.
PORADA: Twoja funkcja ShowBooks nie powinna przyjmować tego interfejsu a np. interfejs Predicate<Book>


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
edytowany 3x, ostatnio: nie100sowny
krzysiek050
Interfejs nie musi mieć adnotacji @FunctionalInterface. Jest to jedynie zabezpieczenie przed dodaniem kolejnych niedefaultowych metod
Shalom
Ta adnotacja niczego nie oznacza, wiesz? Nie jest wcale konieczna...
nie100sowny
formatowanie kodu wcięciami też nie jest wcale konieczne, a jednak to robisz
Shalom
@nie100sowny: ale napisałeś i ma on adnotację @FunctionalInterface to wtedy nie musisz tworzyć klasy która go implementuje, a możesz szybko przekazać lambdęco sugeruje jakoby był to warunek konieczny kiedy w rzeczywistości jest to zupełnie nieistotny szczegół. Błędem jest też twierdzenie że Lambda - to szybki sosób na zapis metody / zachowania bez deklarowania klasy implementującej interfejs. Lambda to obiekt reprezentujący anonimową funkcje i z interfejsami nie ma wiele wspólnego, ot dodano taki syntactic sugar, ale to znów pewien szczegół.
nie100sowny
Ok prawda, ale wyznaję zasadę, że osoba która zakłada tutaj pytanie nie chce dostać w odpowiedzi specyfikację języka Java1.8, a łopatologiczną odpowiedź. Kiedyś dorośnie i zacznie korzystać z StackOverflow :P
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Nie da się zrobić lambdy z interfejsu który ma więcej niż 1 metodę (która nie jest default) bo nie byłoby wiadomo którą z tych metod lambda "implementuje".


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
krzysiek050
Jedną niezaimplementowaną metodę ;)
DU
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 4 lata
  • Postów:143
0

No dobra więc tak, zmieniłem CheckBook na:

Kopiuj
public interface Predicate

metodę ShowBook zmieniłem tak:

Kopiuj
public void ShowBooks(ArrayList<Book> book, Predicate<Book> verification)

a tej lambdy niestety nie potrafię zmienić...

edytowany 1x, ostatnio: duzy
nie100sowny
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 dni
  • Lokalizacja:Kraków
  • Postów:402
0
Kopiuj
public void ShowBooks(books, b -> b.startsWith("A"))

Czyli przekazuję funkcji Predykat (który musi zmieniać Book na boolean), w moim przypadku wyświetlone zostaną książki o tytule zaczynającym się wielką literą A


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
edytowany 2x, ostatnio: nie100sowny
DU
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 4 lata
  • Postów:143
0

No właśnie nie bardzo to działa, tzn w ogóle nie działa - nie kompiluje się.

Kopiuj
public void ShowBooks(ArrayList<Book> book, Predicate<Book> verification)

Typ Predicate nie jest generyczny

Kopiuj
oLib.ShowBooks(book, b -> b.titleBook);

The method ShowBooks(ArrayList<Book>, (<no type="type"> b) -> {}) is undefined for the type OptionLibrary

edytowany 1x, ostatnio: duzy
nie100sowny
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 dni
  • Lokalizacja:Kraków
  • Postów:402
0

Predykat to metoda, która Book zamienia do boolean. A Ty cały czas zmieniasz Book na String.


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
DU
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 4 lata
  • Postów:143
0

Ciężki temat, czyli w Predicate musi być tylko jedna metoda typu boolean więc najlepiej jakby to była metoda generyczna jeśli chcę wypisać wszystkie wartości książki, tak?

nie100sowny
  • Rejestracja:prawie 9 lat
  • Ostatnio:5 dni
  • Lokalizacja:Kraków
  • Postów:402
0

Nie do końca chyba rozumiesz, polecam więcej poczytać.

  1. Chcesz napisać metodę wyświetlającą listę książek.
  2. Chcesz aby ta metoda była bardziej ogólna tj. dawała możliwość np. zawężania wyników.

W starej Javie musiałbyś napisać to tak:

Kopiuj
    public interface DecisionMaker{
        boolean decideWhetherToShow(Book book);
    }
    
    public void showBooks(List<Book> books, DecisionMaker decisionMaker){
        for (Book book : books){
            if(decisionMaker.decideWhetherToShow(book)){
                System.out.print(book);
            }
        }
    }

   public void test(){
        DecisionMaker titleNotEmptyDecisionMaker = new DecisionMaker() {
            @Override
            public boolean decideWhetherToShow(Book book) {
                return book.getTitle() != null;
            }
        };
        List<Book> books = new ArrayList<>();
        
        showBooks(books, titleNotEmptyDecisionMaker)
    }

W Javie 1.8 nie trzeba już tworzyć tej anonimowej klasy:

Kopiuj
public void test(){
        List<Book> books = new ArrayList<>();

        showBooks(books, b -> b.getTitle() != null);
    }
    }

Dodatkowo nie musisz nawet mieć interfejsu DecisionMaker a wykorzystać Predicate<Book>

EDIT: Jeżeli chcesz przekonwertować listę książek na listę tytułów to nie używasz Predicate (bo on konwertuje Book na warunek logiczny boolean), a innego interfejsu np. Function<Book, String> który jak sama nazwa mówi jest funkcją która przyjmuje Book, a zwraca String.


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"
edytowany 5x, ostatnio: nie100sowny
DU
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 4 lata
  • Postów:143
0

Ok już mniej więcej rozumiem, w takim wypadku jeśli mógłbyś powiedzieć jak to wykorzystać bez interfejsu byłbym wdzięczny.

PS. Tutaj jest błąd, a raczej nie błąd bo wszystko się kompiluje ale daje wynik [Book@41629346]

Kopiuj
public void showBooks(List<Book> books, DecisionMaker decisionMaker){
        for (Book book : books){
            if(decisionMaker.decideWhetherToShow(book)){
                System.out.print(book); //to nie wyświetla poprawnie
                System.out.print(book.titleBook); //to już tak, jest jakiś patent aby nie wypisywać book.title, book.author, book.costam?
            }
        }
    }
edytowany 1x, ostatnio: duzy
datdata
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 7 lat
  • Postów:957
0

Zaimplementuj toString().


"A human being should be able to change a diaper, plan an invasion, butcher a hog, conn a ship, design a building, write a sonnet, balance accounts, build a wall, set a bone, comfort the dying, take orders, give orders, cooperate, act alone, solve equations, analyze a new problem, pitch manure, program a computer, cook a tasty meal, fight efficiently, die gallantly. Specialization is for insects." Robert Heinlein.
DU
System.out.println(book.toString()); takie coś zwraca dalej to samo :P
nie100sowny
Zaimplementuj (czyli napisz) w klasie Book metodę toString. Jak nie wiesz jak to kup książkę do Javy :P.
DU
ok, ok rozumiem, mam trudności z zapamiętywaniem nazw, czasem czegoś używam i jakbyś zapytał co to, to bym nie powiedział bo nie pamiętam nazwy :P
DU
  • Rejestracja:prawie 9 lat
  • Ostatnio:prawie 4 lata
  • Postów:143
0

Mógłby mi ktoś powiedzieć jak wykorzystać lambdę bez wykorzystania interfejsu?

nie100sowny
OK odpowiem, musisz kupić książkę do Javy 1.8, uważnie przeczytać, przerobić przykłady i odpowiedź sama się znajdzie.
DU
Szkoda, że do 1.8 nie mam, cóż przed kupnem poszperam jeszcze w sieci bo nie bardzo mnie stać na kupno książek >100pln
nie100sowny
Normalnie proponowałbym tutorial np. od Oracle, ale w Twoim przypadku bardziej potrzebne są materiały "za rączkę"
DU
No w sumie lepiej mi się czyta z kartek niż z monitora ;) niemniej jednak dziękuję za radę! Tak swoją drogą wydaje mi się, że szybciej jest się od kogoś nauczyć niż samemu, dlatego zadałem pytanie ;)
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)