简体   繁体   中英

Java Generics WildCard - How can I use generic with Lambda here?

I am trying to create a generic method. My dtos are:

public class Master {
    private String string;
    private Date date;

    public String getString() {
        return this.string;
    }

    public Date getDate() {
        return this.date;
    }

    public void setString(String string) {
        this.string = string;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}

My Child class which extends Master is:

public class Child extends Master {

    private Date newDate;

    public Date getNewDate() {
        return this.newDate;
    }

    public void setNewDate(Date newDate) {
        this.newDate = newDate;
    }
}

Now, what I want to do is create a generic method to get -

public static <T extends Master> Map<String, Map<Date, List<T extends Master>>> getRecalculateMasterMappedByInstrumentIdAndDate(List<T extends Master> masters) {
        return masters.stream().collect(Collectors.groupingBy(Child::getString, Collectors.groupingBy(x -> org.apache.commons.lang3.time.DateUtils.truncate(x.getDate(), Calendar.DAY_OF_MONTH))));
    }

The above is giving me an error during compile time. How can I write a generic method for the same?

Remove the bound after the declaration:

  • Return type: Map<String, Map<Date, List<T>>>
  • Parameter type: List<T> masters .

You only use bounds with wildcards ( ? ), or in the declaration of the type variables.

You have to understand the difference between the declaration of a type variable and the use of the type variable. When you write

public static <T extends Master> Map<String, Map<Date, List<T>>>
    getRecalculateMasterMappedByInstrumentIdAndDate(List<T> masters) {
    …
}

The <T extends Master> declares the type variable T including the constraint that T must be a subtype of Master . The other occurrences of T within the return type Map<String, Map<Date, List<T>>> and the parameter type List<T> are using the type variable T and don't need to repeat (and are in fact not allowed to repeat) the bounds of T .

Note that you also have to use Master::getString in the method implementation as you can't assume that T is a Child . It may be Child , but the caller can also use Master or any subclass of it for T . Thankfully, getString has been defined in Master anyway, so you don't need to assume Child here.

I was able to solve with the help of folks here. Thank you, guys. My solution:

public static <T extends Master> Map<String, Map<Date, List<T>>> getMastersMappedByInstrumentIdAndDateForRecalculation(List<T> masters) {
        return masters.stream().collect(Collectors.groupingBy(Master::getString, Collectors.groupingBy(x -> org.apache.commons.lang3.time.DateUtils.truncate(x.getDate(), Calendar.DAY_OF_MONTH))));
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM