Upper-bounded wildcards, which you specify using extends, are useful for reading from a data structure. You can support writing to a data structure using lower-bounded wildcards.
Further, the original meetings multimap consists of java.sql.Date objects. Perhaps it was directly loaded from a database application. You want the new multimap to consist of java.util.Date objects. public void testFilter() { MultiHashMap<String,java.sql.Date> meetings= new MultiHashMap<String,java.sql.Date>(); meetings.put("iteration start", createSqlDate(2005, 9, 12)); meetings.put("iteration start", createSqlDate(2005, 9, 26)); meetings.put("VP blather", createSqlDate(2005, 9, 12)); meetings.put("brown bags", createSqlDate(2005, 9, 14)); MultiHashMap<String,java.util.Date> mondayMeetings = new MultiHashMap<String,java.util.Date>(); MultiHashMap.filter(mondayMeetings, meetings, new MultiHashMap.Filter<java.util.Date>() { public boolean apply(java.util.Date date) { return isMonday(date); } }); assertEquals(2, mondayMeetings.size()); assertEquals(2, mondayMeetings.get("iteration start").size()); assertNull(mondayMeetings.get("brown bags")); assertEquals(1, mondayMeetings.get("VP blather").size()); } private boolean isMonday(Date date) { Calendar calendar = GregorianCalendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY; } private java.sql.Date createSqlDate(int year, int month, int day) { java.util.Date date = DateUtil.createDate(year, month, day); return new java.sql.Date(date.getTime()); } You can use lower-bounded wildcards on the MultiHashMap filter method to allow transforming from java.sql.Date values to java.util.Date values. In the implementation, the target argument of the filter method is a MultiHashMap whose value type (V) has a lower bound of V. This is expressed as ? super V. This means that the value type (V) of the target MultiHashMap can be the same as V or a supertype of V. The meetings example works because java.util.Date is a supertype of java.sql.Date. ... public class MultiHashMap <K,V> { private Map<K, List<V>> map = new HashMap<K, List<V>>(); ... public interface Filter<T> { boolean apply(T item); } public static <K,V> void filter( final MultiHashMap<K, ? super V> target, final MultiHashMap<K, V> source, final Filter<? super V> filter) { for (K key : source.keys()) { final List<V> values = source.get(key); for (V value : values) if (filter.apply(value)) target.put(key, value); } } } |