[英]Java 8 Map of Collections remove element from collection and remove entry if empty
我有一個地圖,其值是一個集合。 給定一個鍵,我想刪除該集合的一個元素並將其返回,但如果該集合為空,我還想刪除該條目。 有沒有辦法使用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()
返回的值。
嗯,它甚至比你現有的還要丑陋,但是有一種方法,我想:
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
,而不是該集合中的單個元素。
或者您可以使用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();
}
有沒有辦法使用Java 8的眾多新Map方法之一以簡短的方式完成此操作?
JDK8沒有新方法可以改善您的代碼,無論是在可讀性還是高效方面。
如果你這樣做是為了鍛煉你自己,那么我可以在某種程度上理解為什么你想要縮短代碼( 如果可能的話 )但是當涉及到生產代碼時應該避免打高爾夫球,而是采用那種方法最具可讀性和可維護性; 沒關系,如果它更長。
你的方法很好。
Guava的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);
}
如果映射沒有給定鍵的條目,則現有解決方案和上述解決方案都會拋出異常。 您可以選擇更改代碼來處理此問題:
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);
}
我完全贊同@NicholasK。 這里沒有理由使用任何流或lambdas。
你的方法非常好。 我想要添加的唯一內容是將其設為通用:
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;
}
此方法適用於返回有效迭代器的任何集合(映射值)。
/* 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));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.