2016-04-29 55 views
0

我有一個包含日期和產品發佈類型的地圖。使用地圖的鍵從值中選擇最高數據 - Java

示例(「2015/04/12」,「1 | Prod43」);

我的地圖值:

2015/08/27 1|Prod23 
2015/12/15 1|Prod55 
2016/04/08 1|Prod09 
2016/04/09 2|Prod09 
2016/04/12 3|Prod09 

我想保持2周的ArrayList,dateList遏制鍵,prodList的值。但是約束是,在四月份,Prod09有三個版本,在「|」之前用數字表示。符號。我只想要任何月份的最新版本的產品。

在這裏,April有3個版本,我只想把第三版發佈到我的arrayList中。

需要我的ArrayList是這樣的:

dateList -> ["2015/08/27","2015/12/15","2016/04/12"] 
prodList - >["1|Prod23","1|Prod55","3|Prod09"] 

代碼:

{ 
Map<String,String> dateMap = new TreeMap<String,String>(); 
      dateMap.put("2015/08/27","1|Prod23"); 
      dateMap.put("2015/12/15","1|Prod55"); 
      dateMap.put("2016/04/08","1|Prod09"); 
      dateMap.put("2016/04/09","2|Prod09"); 
      dateMap.put("2016/04/12","3|Prod09"); 
      String test1=""; 
      String test2=""; 
      int count=0; 
      List<String> prodList = new ArrayList<String>(); 
      List<String> dateList = new ArrayList<String>(); 

      for (Map.Entry<String, String> entry : dateMap.entrySet()) 
         { 
          String key = entry.getKey().substring(0,7); 
          String dateValue = entry.getValue(); 

          if(("").equals(test1)){ 
           test1=key; 
           test2=key; 
          } 
          if(!(test2.equals(key))){ 
           dateList.add(key); 
           prodList.add(dateValue); 
           test2=key; 
          }else{ 
           if(count<1){ 
           dateList.add(key); 
           prodList.add(dateValue); 
           test2=key; 
           count++; 
           } 
          } 

         } 
        System.out.println("dateList: "+dateList); 
        System.out.println("prodList: "+prodList); 
} 

在上面的方法,我已經做到了查找最大的2日最新發布的,但如果釋放增加,這種方法會失敗。任何人都可以請建議我一個更好的方法來做到這一點。非常感謝您的幫助。

+0

如果兩個產品在某個特定的日期發佈?在地圖鍵中應該是唯一的。 – Kajal

+0

這不會發生在我的方案中,我的地圖的值從數據庫表填充,其中日期是主鍵。所以可能性可能是同一個月的不同日期。你能幫助 – Disera

+0

你上面的代碼中的輸入鍵是不正確的。也許你想再次訪問它們? – Aakash

回答

2

由於您使用TreeMap,這是根據它的鍵的自然順序進行排序,我們可以利用這個特性來編寫一些代碼。我可以很快拿出這段代碼,也許它可以幫助你

Map<String, String> dateMap = new TreeMap<String, String>(); 
dateMap.put("2015/08/27", "1|Prod23"); 
dateMap.put("2015/12/15", "1|Prod55"); 
dateMap.put("2016/04/08", "1|Prod09"); 
dateMap.put("2016/04/12", "3|Prod09"); 
dateMap.put("2016/04/09", "2|Prod09"); 

String lastKey = ""; 
String currentKey = ""; 
List<String> date = new ArrayList<String>(); 
List<String> release = new ArrayList<String>(); 
for(Map.Entry<String, String> entry : dateMap.entrySet()) { 
    String temp = entry.getKey(); 
    currentKey = temp.substring(0, 7); 
    if(currentKey.equals(lastKey)){ // another release in same month as previous release 
     // Remove last release details 
     date.remove(date.size() - 1); 
     release.remove(release.size() - 1); 
     // Add current release deetails 
     date.add(temp); 
     release.add(entry.getValue()); 
     lastKey = currentKey; 
    } else { // first release in this month 
     // Add current release deetails 
     date.add(temp); 
     release.add(entry.getValue()); 
     lastKey = currentKey; 
    } 
} 

也許你的代碼想出更精緻的版本。下面是上面代碼的輸出

[2015/08/27, 2015/12/15, 2016/04/12] 
[1|Prod23, 1|Prod55, 3|Prod09] 
+0

非常感謝!非常有用,儘管我使用了比較器方法以及Treemap <>,因爲它區分大小寫。 – Disera

+1

字符串比較默認情況下區分大小寫,所以要繞過,當然你必須使用比較器。 – Aakash

3

夫婦意見:

  • 您與串聯的 「|」字符表明您嘗試將2個數據保存在單個值中。 (這是不好的信息實踐,如果你真的需要這兩者,而是爲每個值創建一個帶有字段的新類,或者可以使用列表的索引作爲相對等級的隱含值,如我在下面所做的那樣)。
  • 地圖(和其他數據結構)可以保持任何對象,包括java.util.Date(或更現代的時間類之一),數組,List S等
  • 目前尚不清楚爲什麼你要映射從日期到產品發佈。

對於你的問題的目的,類似於以下地圖的結構可以是更加有用:

{產品=> [ReleaseDate1,ReleaseDate2,...]}

其中產品可以是「Prod23」,「Prod55」,「Prod09」等,地圖的值將爲List或數組,可能爲空。 (List s更容易添加到)。

得到「Prod12」最新發布的日期,你會做這樣的事情:

dates = prodMap.get("Prod12"); 
lastDate = dates.get(dates.size()); // assuming they where inserted in order 

有排序的集合(或者你可以提供一個比較器),以確保收集的順序。

+0

@ fr13d謝謝!在這裏,我不想收集單個產品的所有發佈日期,因爲最新版本將包含所有必要的信息,所以我想刪除以前的版本並保留最新版本。有沒有辦法做到這一點? – Disera

+1

@Disera,如果你只想保留最新的發佈日期,不要保留一個'List'(或其他'Collection'),只需在地圖中保留一個Date作爲值,並且每次覆蓋新版本日期可用。尚未發佈的產品將具有'null'。 – fr13d

+0

@Disera你應該在你的問題中提出這個要求。它改變了整個問題。 –

0

而不是創建一個列表String來保存日期,我寧願準備一個列表Date。除非你有相同的格式,否則將String轉換爲Date並不難。

這將幫助您轉換問題代碼中提供的當前格式。

 DateFormat format = new SimpleDateFormat("yyyy/MM/dd", Locale.ENGLISH); 
     Date  date = format.parse("2016/04/26"); 

這裏的功能將幫助您獲取任意數量的提供日期的最新日期。

public static Date findLatest (Date... dates) { 
     Date date = dates[0]; 
     for (int i = 1; i < dates.length; i++) { 
      if (dates[i].after(date)) { 
       date = dates[i]; 
      } 
     } 
     return date; 
    } 
0

問題重新定義

這一問題的重新定義作者的問題陳述的評論this Answer。只需要每個產品的最新日期。

java.time

Java 8及更高版本包括java.time框架。這些日期時間類代替了糟糕的設計和麻煩的舊日期時間類,如java.util.Date/.Calendar。新類包括LocalDate僅用於日期值,YearMonth類用於整月組織數據而非單一日期。

地圖產品代碼約會

鑑於修訂後的問題,跟蹤每個產品的最新日期,我們需要一個Map其中產品代碼是關鍵,最新的日期,LocalDate,是值。

Map< String , LocalDate > map = new HashMap<>(); 

如果你能得到你的輸入數據使用標準ISO 8601格式的日期,我們就可以很簡單地輸入數據。

map.put("Prod23" , LocalDate.parse("2015-08-27")); 
map.put("Prod55" , LocalDate.parse("2015-12-15")); 
map.put("Prod09" , LocalDate.parse("2016-04-08")); 

現在我們將爲相同的Prod09鍵放置不同的更新日期。 Map用新值(「2016/04/09」的LocalDate)替換之前的值(「2016-04-08」的LocalDate)。引用Map::put的文檔:

如果映射先前包含密鑰的映射,則舊值由指定值替換。

map.put("Prod09" , LocalDate.parse("2016-04-09")); 

而且具有更晚的日期,四月12日再次更換它。

map.put("Prod09" , LocalDate.parse("2016-04-12")); 

mergeput

這種方法至今假定輸入數據始終是以後的日期,按時間順序到達。如果數據可能包含更早的日期,但我們總是想保留最新的日期,那麼我們有一個問題。爲了看到這個問題,我們可以切換兩條線,在12日之後放置4月9日。

// Calling `put` with dates arriving *not* in chronological-order. 
Map< String , LocalDate> mapP = new HashMap<>(); 

mapP.put ("Prod23" , LocalDate.parse ("2015-08-27")); 
mapP.put ("Prod55" , LocalDate.parse ("2015-12-15")); 
mapP.put ("Prod09" , LocalDate.parse ("2016-04-08")); 
mapP.put ("Prod09" , LocalDate.parse ("2016-04-12")); 
mapP.put ("Prod09" , LocalDate.parse ("2016-04-09")); 

System.out.println ("mapP: " + mapP); 

您可以在輸出中看到第9個替換了第12個,而不是我們想要的。

MAPP:{Prod23 = 2015年8月27日,Prod55 = 2015年12月15日,Prod09 = 2016年4月9日}

修復的方法是定義一個比較功能要被施加每次我們嘗試添加到MapMap接口爲此定義了merge方法,其中我們通過BiFunction的實現。聽起來很花哨,但實際上很簡單。一行代碼使用ternary operator,在Java 8及更高版本中新增了一些Lambda syntax

我們定義我們的BiFunction來比較一對LocalDate對象,並返回其中一個對象(isAfter另一個對象)。如果相同,我們將返回哪一個都不重要。

隨着我們的BiFunction定義,我們在Map上撥打merge而不是put

// Calling `merge` with dates arriving *not* in chronological-order. 
Map< String , LocalDate> mapM = new HashMap<>(); 

BiFunction<LocalDate , LocalDate , LocalDate> latestLocalDate = (ld1 , ld2) -> { 
    return (ld1.isAfter (ld2) ? ld1 : ld2); 
}; 

mapM.merge ("Prod23" , LocalDate.parse ("2015-08-27") , latestLocalDate); 
mapM.merge ("Prod55" , LocalDate.parse ("2015-12-15") , latestLocalDate); 
mapM.merge ("Prod09" , LocalDate.parse ("2016-04-08") , latestLocalDate); 
mapM.merge ("Prod09" , LocalDate.parse ("2016-04-12") , latestLocalDate); 
mapM.merge ("Prod09" , LocalDate.parse ("2016-04-09") , latestLocalDate); 

System.out.println ("mapM: " + mapM); 

在此輸出,你可以看到第9沒更換月12日。第9位被忽略,第12位保持原位,作爲我們最新的關鍵值Prod09

MAPM:{Prod23 = 2015年8月27日,Prod55 = 2015年12月15日,Prod09 = 2016年4月12日}

格式化圖案

爲了解析的輸入數據如問題所示,定義一個DateTimeFormatter對象,並傳遞給parse的調用。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); 
… LocalDate.parse("2015/08/27" , formatter) …