代码之家  ›  专栏  ›  技术社区  ›  Ricola

Java 8集合映射从集合中删除元素,如果为空,则删除条目

  •  11
  • Ricola  · 技术社区  · 7 年前

    我有一个值为集合的映射。给定一个键,我想删除集合的一个元素并返回它,但如果集合为空,我还想删除该项。使用Java8的众多新映射方法中的一种,有没有一种方法可以简单地做到这一点?

    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() .

    6 回复  |  直到 7 年前
        1
  •  5
  •   Eugene    7 年前

    好吧,这比你已经准备好的还要丑陋,但我想有一种方法:

    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 诸如此类的返回 价值 ,你的情况是 Stack/Set/List ,而不是该集合中的单个元素。

        2
  •  4
  •   Naman    7 年前

    或者你也可以用 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();
    }
    
        3
  •  2
  •   Ousmane D.    7 年前

    有没有一种方法可以使用众多的新方法中的一种以简短的方式做到这一点 Java8的映射方法?

    从JDK8开始,没有新的方法可以提高代码的可读性或效率。

    如果可能的话 )但是当涉及到产品代码时,应该避免打高尔夫,而是采用可读性和可维护性最好的方法;长一点也不要紧。

    你的方法很好。

        4
  •  2
  •   MikeFHay    7 年前

    Guava's Multimap 如果逻辑为空,则处理移除集合。您可以在两行中获得与方法相同的行为:

    public static String removeOne(ListMultimap<Integer, String> map, int key) {
        List<String> stack = map.get(key);
        return stack.remove(stack.size() - 1);
    }
    

    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);
    }
    
        5
  •  1
  •   ETO    7 年前

    我完全同意@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;
    }
    

        6
  •  -1
  •   Jurgen De Landsheer    7 年前
    /* 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));
        }
    }