簡體   English   中英

Apache CollectionUtils的良好用法

[英]Good uses for Apache CollectionUtils

我在一年前左右發現CollectionUtils類,並且其中一些方法(如收集,轉換)看起來確實很酷,但是,我還沒有找到一種在語法上不會更干凈和/或更容易編寫它的方法的用途。一個簡單的循環邏輯。

有沒有發現這些方法(transform,predicatedCollection,collect等)的唯一\\有用用法,例如以轉換器或謂詞為參數的方法?

我認為關鍵是設計/編碼的靈活性。

如果您只有一個用例(例如,選擇滿足某些特定條件的集合的成員),則可以手動編寫相對簡單的循環。 另一方面...

假設這組可能的條件變大了,或者甚至可以在運行時動態地組成(甚至基於用戶輸入/交互而動態地組成)。 或者假設存在一些可能由運算符組成的非常復雜的條件(例如,A和B,C而不是D等)甚至更多情況。

假設已經做出選擇,還需要對結果集合進行一些其他處理。

現在,考慮一下用強力的嵌入式方法編寫上述代碼可能會導致的代碼結構:一個外部循環,其中包含一個復雜的決策過程來確定要執行的測試,並與執行一個測試的代碼混合在一起集合中“尚存”成員的更多或更多內容。 這樣的代碼往往難以理解(尤其是隨着維護時間的流逝),並且很難在沒有引入缺陷風險的情況下進行修改。

因此,關鍵是要在每個方面都采取一種策略:

  • 基本的“選擇內容”過程
  • 表達基本標准的謂詞,
  • 組合構成謂詞的運算符,以及
  • 根據值運行的變壓器

可以獨立進行編碼和測試,然后根據需要合並在一起。

當您有可能的對象替代表示形式時,collect()很有用。

例如,最近我正在處理一段代碼,該代碼需要匹配來自兩個不同來源的對象列表。 這些對象屬於不同的類,因為它們在代碼中的不同點使用,但出於我的目的,它們具有相同的相關概念(即,它們都有一個ID,都有一個屬性路徑,都有一個“級聯”標志等)。 。

我發現,定義這些屬性的簡單中間表示(作為內部類),為兩個具體對象類定義轉換器(再次非常簡單,因為它只是使用相關的訪問器方法來獲取屬性)要容易得多,然后使用collect()將我的傳入對象轉換為中間表示形式。 一旦它們存在,我就可以使用標准的Collections方法來比較和操縱這兩個集合。

因此,作為一個(半)具體示例,我需要一種方法來檢查表示層中的對象集是否是數據層中緩存的對象的子集。 使用上面概述的方法,將執行以下操作:

public boolean isColumnSubset(PresSpec pres, CachedDataSpec dataSpec)
{
   final List<IntermediateRepresentation> presObjects = CollectionUtils.collect(pres.getObjects(), PRES_TRANSFORMER);
   final List<IntermediateRepresentation> dataObjects = CollectionUtils.collect(dataSpec.getCached(), DATA_TRANSFORMER);

   return dataObjects.containsAll(presObjects);
}

對我來說,這是更加易讀,到最后一行輸送什么樣的方法做的 ,比用循環相當於一個真正意義上的:

public boolean isColumnSubset(PresSpec pres, CachedDataSpec dataSpec)
{
   for (PresSpecificObject presObj : pres.getObjects())
   {
      boolean matched = false;
      for (CachedDataObject dataObj : dataSpec.getCached())
      {
         if (areObjectsEquivalent(presObj, dataObj)) // or do the tests inline but a method is cleaner
         {
            matched = true;
            break;
         }
      }

      if (matched == false)
      {
         return false;
      }
   }

   // Every column must have matched
   return true;
}

兩者可能差不多有效,但是就可讀性而言,我會說第一個更容易立即理解。 盡管總體上出現了更多的代碼行(由於定義了一個內部類和兩個轉換器),但是將遍歷實現與實際的“真或假”邏輯分開可以使后者更加清晰。 另外,如果您有任何KLOC指標,它也不能成為珠。 ;-)

盡管我在原則上同意Uri,但沒有閉包,函數文字或其他內容,但Java實際使用諸如collect,transform等方法會帶來很高的語法成本。在很多情況下,實際的代碼行相同或更大比起您編寫了簡單的循環。 不過,addAll,removeAll及其所有不將函數對象作為參數的朋友都是必不可少的。

所有這些同樣適用於同樣出色的Google Collections API

令人遺憾的是,Sun能夠解決Java 7中的這些問題,但看來並沒有解決這些問題。 懦夫。

我不確定我是否同意你的說法...

一個簡單的循環增加了復雜性,並且比具有明智名稱的調用的“可讀性和明顯性”低。

重構傳福音者會聲稱,您的目標通常應該是創建調用其他操作的簡單函數和簡短函數。 盡管addAll,find和此類方法很容易實現,但要避免它們,將要求讀者掌握比單個單詞更復雜的內容,並可能導致代碼復制。

恕我直言,CollectionUtils實際上提供了比標准Java集合庫更簡潔的操作。

盡管我們不使用CollctionUtils,但我們已經實現了一些類似的實用程序,這些實用程序是我們自己以及經常使用的實用程序

空(集合c)

測試集合,字符串等是否為空

擁有(...)

只返回!empty(...)

mapToProperty(Collection c,String屬性,類newType)

這會使用反射將T1的集合映射到T2的集合以調用“屬性”

內爆(Collection c,String sep)

帶c元素的分隔字符串

暫無
暫無

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

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