javagenericslambdajava-stream

Java Streams usage with generics


I have a the below class:

@Data
public class PagedSchoolDto {
    private final Integer count;
    private final Map<String, List<School>> content;
    private final String pagingState;
    private final Boolean hasNext;

    public PagedSchoolDto(final Slice<School> slice) {
        this.content = slice.getContent().stream().collect(
                Collectors.groupingBy(School::getId, () -> new TreeMap<>(new UUIDComparator()), Collectors.toList()));
        this.count = slice.getContent().size();
        this.hasNext = slice.hasNext();
        this.pagingState = getPagingState(slice);
    }

    @Nullable
    private static String getPagingState(final Slice<School> slice) {
        if (slice.hasNext()) {
            CassandraPageRequest pageRequest = (CassandraPageRequest) slice.nextPageable();
            return pageRequest.getPagingState().toString();
        } else {
            return null;
        }
    }
}

Now, I want to make my code generic so that I can use this class for other object types as well like below:

@Data
public class PagedDto<T> {
    private final Integer count;
    private final Map<String, List<T>> content;
    private final String pagingState;
    private final Boolean hasNext;

    public PagedDto(final Slice<T> slice) {
        this.content = slice.getContent().stream().collect(
                Collectors.groupingBy(<T>::getId, () -> new TreeMap<>(new UUIDComparator()), Collectors.toList()));
        this.count = slice.getContent().size();
        this.hasNext = slice.hasNext();
        this.pagingState = getPagingState(slice);
    }

    @Nullable
    private static <T> String getPagingState(final Slice<T> slice) {
        if (slice.hasNext()) {
            CassandraPageRequest pageRequest = (CassandraPageRequest) slice.nextPageable();
            return pageRequest.getPagingState().toString();
        } else {
            return null;
        }
    }

}

All my classes have a property called ID which is type UUID so the comparator should work fine all generics types. The issue is I'm not sure how to write the Collectors.groupingBy's function and supplier code as the second snippet is giving compilation error.


Solution

  • Your generic type T is unspecified, e.g. 'Object' which does not provide the method getId. In order to access getId in the generic code, T must extend an interface with the getId method, which is implemented by any class that is used with PagedDto:

    public interface WithId {
        UUID getId();
    }
    
    
    public class School implements WithId {
    
        private UUID id;
    
        @Override
        public UUID getId() {
            return id;
        }
    
    
    public class PagedDto<T extends WithId> {
    ...