这是解决此问题的通用方法。下面的groupBy
方法需要2到3个参数。
- 类型为
List<E>
的collection
- 类型为
Function<E, K>
的keyFn
(键)
- (可选)类型为
Function<E, V>
或简单的E
的valueFn
(值)
我在下面包含了一些单元测试。
CollectionUtils.java
package org.example.util;
import static java.util.Collections.unmodifiableMap;
import static java.util.stream.Collectors.*;
import java.util.*;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import java.util.function.Function;
public class CollectionUtils {
public static <E, K, V> Map<K, List<V>> groupBy(
Collection<E> collection, Function<E, K> keyFn, Function<E, V> valueFn) {
return collection.stream()
.map(item -> new SimpleEntry<K, V>(keyFn.apply(item), valueFn.apply(item)))
.collect(groupingBy(Entry::getKey, mapping(Entry::getValue, toList())));
}
public static <E, K> Map<K, List<E>> groupBy(Collection<E> collection, Function<E, K> keyFn) {
return groupBy(collection, keyFn, Function.identity());
}
public static <K, V> Map<K, V> immutableMapOf(K k1, V v1, K k2, V v2) {
Map<K, V> mutableMap = new HashMap<>();
mutableMap.put(k1, v1);
mutableMap.put(k2, v2);
return unmodifiableMap(mutableMap);
}
}
CollectionUtilsTest.java
package org.example.util;
import static java.util.Arrays.asList;
import static org.example.util.CollectionUtils.*;
import static org.junit.Assert.*;
import java.util.*;
import org.junit.Test;
import org.slf4j.*;
public class CollectionUtilsTest {
private static final Logger logger = LoggerFactory.getLogger(CollectionUtilsTest.class);
private static final List<Map<String, String>> data =
asList(
immutableMapOf("Username", "Batman", "Role", "Leader"),
immutableMapOf("Username", "Robin", "Role", "Subordinate"),
immutableMapOf("Username", "Superman", "Role", "Leader"));
@Test
public void testGroupBy() {
logger.info("Test groupBy(Collection<E>, Function<E, K>, Function<E, V>)");
Map<String, List<String>> grouped = groupBy(data, m -> m.get("Role"), m -> m.get("Username"));
logger.info("Checking keys...");
assertNotNull(grouped.get("Leader"));
assertNotNull(grouped.get("Subordinate"));
logger.info("Checking values...");
assertEquals("Batman", grouped.get("Leader").get(0));
assertEquals("Superman", grouped.get("Leader").get(1));
assertEquals("Robin", grouped.get("Subordinate").get(0));
}
@Test
public void testGroupBySimple() {
logger.info("Test groupBy(Collection<E>, Function<E, K>)");
Map<String, List<Map<String, String>>> grouped = groupBy(data, m -> m.get("Role"));
logger.info("Checking keys...");
assertNotNull(grouped.get("Leader"));
assertNotNull(grouped.get("Subordinate"));
logger.info("Checking values...");
assertEquals("Batman", grouped.get("Leader").get(0).get("Username"));
assertEquals("Superman", grouped.get("Leader").get(1).get("Username"));
assertEquals("Robin", grouped.get("Subordinate").get(0).get("Username"));
}
}