Bernardo Rodrigues
Bernardo Rodrigues

Reputation: 13

bad return type in lambda expression cannot convert Object to T

I have this lazy iterator that pretty much receives a function and a string as parameters, goes to an API, receives a DTO from the API and converts that DTO to a domain object (in this case an Event). This Event, as seen below is made up of an Artist and several Tracks. My problem (not only here) is that, when in my EventIterator, I try to populate my artistSupplier by passing a lambda expression, I get the error "Bad return type in lambda expression ArtistDto cant be converted to T".

public class EventIterator<T, U, R> extends SetListIterator<T, U, R> implements Iterator<R> {

private Function<U, T[]> function;
private String s;
private LastfmApi lastfmApi;

public EventIterator(String s, Function<U, T[]> function, LastfmApi lastfmApi) {
    this.lastfmApi = lastfmApi;
    this.s = s;
    this.function = function;
    page = 1;
}

@Override
public R convertToDomainType(T[] ret) {
    EventDto [] eventDtos = (EventDto[]) ret;
    LinkedList list = new LinkedList<Event>();
    for (EventDto e:
         eventDtos) {
        Event event = new Event(
                e.getArtistName(),
                e.getEventDate(),
                e.getTour(),
                e.getTracksNames(),
                getTracks(e.getTracksNames(), e.getArtistName()),
                e.getSetListId()
         );
        event.setArtistSupplier(
                (b, c) -> new ArtistIterator<R, U, T>(
                        e.getArtistName(),
                        (a) -> lastfmApi.getArtistInfo(e.getArtistName())
                )
        );
        list.add(event);
    }
    return (R) list;
}


public class Event {

private Artist artist;
private Function<String, Artist> artistSupplier;
private String artistName;
private String eventDate;
private String tour;
private String [] tracksNames;
private Iterable<Track> tracks;
private String setlistId;

public void setArtistSupplier(Function<T, U> supplier) {
    this.artistSupplier = supplier;
}

public Artist artist(String s) {
    return artist = (Artist) artistSupplier.apply((T) s);
}

}

public class Artist {

private String name;
private String bio;
private String url;
private String [] imagesUri;
private String mbid;

}

public abstract class SetListIterator<T, U, R> implements Iterator<R> {

protected String s;
protected int page;
protected T []dtos;

@Override
public R next() {
    T[] ret = dtos;
    if (!hasNext())
        throw new NoSuchElementException();
    dtos = moveNext();
    return convertToDomainType(ret);
}

public abstract T[] moveNext();

public abstract R convertToDomainType(T[] ret);
}

Upvotes: 1

Views: 10904

Answers (1)

user4413257
user4413257

Reputation:

Your artistSupplier function is defined as Function<String, Artist> with single String input and Artist output, while you are trying to pass some function which accepts two arguments (b,c) and returns ArtistIterator:

event.setArtistSupplier(
        (b, c) -> new ArtistIterator<R, U, T>(
                e.getArtistName(),
                (a) -> lastfmApi.getArtistInfo(e.getArtistName())
        )
);

Since your code does include Event#setArtistSupplier implementation I can just assume, that it is something like this:

setArtistSupplier(Function<String,Artist> function) {artistSupplier = function;}

EDIT

What you need to do is:

event.setArtistSupplier((name) -> {
    Artist artist = ...; // convert name to Artist (e. g. load artist based on name)
    return artist;

});

Upvotes: 1

Related Questions