我有一张地图,其值是一个集合。给定一个键,我想删除集合的一个元素并返回它,但是如果集合为空,我也想删除该条目。使用Java 8的众多新Map方法之一,有没有一种简短的方法?
一个简单的例子(我使用一个Stack,但是它可以是一个List,一个Set等)。为了便于说明,我们假设已经检查了地图是否包含键。
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
Stack<String> stack = map.get(key);
String result = stack.pop();
if(stack.isEmpty()){
map.remove(key);
}
return result;
}
我尝试做类似的事情
map.compute(1, (k, v) -> {v.pop(); return v.size() == 0 ? null : v;});
但是,即使确实为空,它也确实删除了该条目,但我不知道如何获取pop()
返回的值。
答案 0 :(得分:5)
嗯,它比您已经使用的要难看,但我想有一种方法:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
String[] removed = new String[1];
map.compute(key, (k, v) -> {
removed[0] = v.pop();
return v.size() == 0 ? null : v;
});
return removed[0];
}
问题是merge/compute
等返回 value ,在您的情况下,它是Stack/Set/List
,而不是该集合中的单个元素。
答案 1 :(得分:4)
或者您也可以使用size
将其重写为:
public static String removeOne(Map<Integer, Stack<String>> map, int key) {
return map.get(key).size() == 1 ? map.remove(key).pop() : map.get(key).pop();
}
答案 2 :(得分:2)
有没有一种方法可以使用众多新方法之一在短时间内完成此操作 Java 8的Map方法?
从JDK8开始,没有新方法可以提高代码的可读性或效率。
如果您这样做是为了自己,那么我可以在某种程度上理解为什么您想缩短代码(如果可能),但是涉及生产代码打高尔夫球应避免,而应采用最易读和可维护的方法;再长也没关系。
您的方法很好。
答案 3 :(得分:2)
Guava's Multimap为您处理remove-collection-if-empty逻辑。您可以在两行中获得与您的方法相同的行为:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
return stack.remove(stack.size() - 1);
}
如果映射没有给定键的条目,则现有解决方案和上述方法均会引发Exception。您可以选择更改代码来处理此问题:
public static String removeOne(ListMultimap<Integer, String> map, int key) {
List<String> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
当然可以使它通用:
public static <K, V> V removeOne(ListMultimap<K, V> map, K key) {
List<V> stack = map.get(key);
if (stack.isEmpty()) {
return null;
}
return stack.remove(stack.size() - 1);
}
答案 4 :(得分:1)
我完全同意@NicholasK。没有理由在这里使用任何流或lambda。
您的方法非常好。我唯一要添加的就是使其通用:
public static <K, E, C extends Collection<E>> E removeOne(Map<K, C> map, K key) {
C col = map.get(key);
Iterator<E> it = col.iterator();
E e = it.next();
it.remove();
if (!it.hasNext()) {
map.remove(key);
}
return e;
}
此方法将适用于任何返回有效迭代器的集合(映射值)。
答案 5 :(得分:-1)
/* quite ugly
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
*/
@Test
public void test() {
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.addAll(Arrays.asList("a", "b"));
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("b", rv);
Assert.assertEquals(1, map.get(1).size());
Assert.assertEquals("a", map.get(1).iterator().next());
}
{
Map<Integer, Stack<String>> map = new HashMap<>();
Stack<String> s = new Stack<String>();
s.add("a");
map.put(1, s);
String rv = Optional.ofNullable(map.get(1)).map(stack -> {
if (!stack.isEmpty()) {
String v = stack.pop();
if (stack.isEmpty()) {
map.remove(1);
}
return v;
}
return null;
}).orElse(null);
Assert.assertEquals("a", rv);
Assert.assertNull(map.get(1));
}
}