簡體   English   中英

在一行的 retainAll 之后將 size() 添加到 keySet()

[英]Add size() to keySet() after retainAll on one line

我正在試驗視圖。 是否可以在不使用 lambda 的情況下在倒數第二行編寫 size() 方法? 如下:

eintraege.retainAll(Arrays.asList(names)).size(); // Does not work


public static int countNames(Map<String, PhoneNumber> phoneBook,
                             String[] names) {
    Set<String> eintraege = phoneBook.keySet();
    eintraege.retainAll(Arrays.asList(names));  
    return eintraege.size();  // Works fine
}

此代碼無法正常工作。

retainAll將刪除所有不在names中的鍵。 .keySet()返回副本。 它返回不同的視圖。 .keySet()返回的內容中刪除元素會將它們從原始地圖中刪除!

因此,此代碼將給出正確的答案...並且還會損壞您的電話簿。

如果您必須使用retainAll ,則必須制作一份副本。 不,沒有辦法鏈接size()調用。

但是,在這里復制是愚蠢的。 你真的只是想,嗯,數名字。 此代碼不會破壞原始電話簿並且速度更快:

int count = 0;
for (String n : names) if (phoneBook.containsKey(n)) count++;
return count;

它還顯示了“擔心台詞”的愚蠢行為。 上面的代碼是 3 行,並且可以按原樣合理地閱讀。 當然,大量使用 lambda 的人會將完全相同的“語義負載”放在一行中。 但這並不是特別常用的代碼風格。 在某些時候,您更多地是在“衡量代碼風格的有效性”,而不是實際衡量代碼的復雜性。 您還會看到毫無用處並使代碼更難閱讀的極端情況:一個.stream().map()等操作執行 18 項不同的操作,全部堆積在一條巨大的線上,並且有些小丑在說:哈! 看! 更短!

牢記數據結構的特征。 list.contains(n)花費的時間隨着列表的大小而增加。 map.containsKey(n)set.contains(n)需要常數時間(或者在TreeMap的情況下,需要的時間與log2(n)成比例,但請記住log2(1_000_000)仍然只有幾十循環。即使對於巨大的輸入,計算機也可以進行對數縮放。

因此,上面的代碼相對較快,但是如果你翻轉它:

for (String n : phoneBook.keySet()) if (names.contains(n)) count++;

這確實會變得非常緩慢,尤其是當names很大的時候。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM