我有一张包含日期和产品发布类型的地图。
示例(" 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个数组列表,dateList
包含值,prodList
表示值。但约束是,在4月份,Prod09有三个版本,在" |"之前用数字表示。符号。我想要任何月份的产品的最新版本。
这里,April有3个版本,我想只将第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);
}
在上面的方法中,我已经完成了查找第二个最新版本的最大值,但如果版本增加,这种方法将失败。任何人都可以建议我更好的方法来做到这一点。非常感谢你的帮助。
答案 0 :(得分:3)
夫妻观察:
java.util.Date
(或其中一个更现代的时间类),数组,List
等。 出于您的问题的目的,类似于以下地图的结构可能更有用:
{Product =&gt; [ReleaseDate1,ReleaseDate2,...]}
产品可能是&#34; Prod23&#34;,&#34; Prod55&#34;,&#34; Prod09&#34;等等,地图的值将是List
或数组,可能为空。 (List
更容易添加)。
要获取&#34; Prod12&#34;的最新版本的日期,您可以执行以下操作:
dates = prodMap.get("Prod12");
lastDate = dates.get(dates.size()); // assuming they where inserted in order
有分类的集合(或者你可以提供一个比较器)来确保集合的顺序。
答案 1 :(得分: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]
答案 2 :(得分: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;
}
答案 3 :(得分:0)
本课题的作者在this Answer的评论中重新定义了问题陈述。只需要每个产品的最新日期。
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
将新值(LocalDate
替换为“2016/04/09”)替换以前的值(LocalDate
为“2016-04-08”)。引用Map::put
的文档:
如果地图以前包含该键的映射,则旧值将替换为指定的值。
map.put( "Prod09" , LocalDate.parse( "2016-04-09" ) );
并在4月12日晚些时候更换它。
map.put( "Prod09" , LocalDate.parse( "2016-04-12" ) );
merge
与put
到目前为止,这种方法假定传入的数据总是用于以后的日期,按时间顺序到达。如果数据可能包含较早的日期,但我们总是希望保留最新日期,那么我们就会遇到问题。为了看到这个问题,我们可以切换两条线,在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-08-27,Prod55 = 2015-12-15,Prod09 = 2016-04-09}
修复是定义每次我们尝试添加Map
时要应用的比较函数。 Map
接口为此目的定义了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个不替换了4月12日。第9个被忽略了,第12个被保留了,作为Prod09
密钥的最新值。
mapM:{Prod23 = 2015-08-27,Prod55 = 2015-12-15,Prod09 = 2016-04-12}
要解析问题中显示的输入数据,请定义DateTimeFormatter
对象,然后转入对parse
的调用。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyy/MM/dd" );
… LocalDate.parse( "2015/08/27" , formatter ) …