我在Java中有一个数组,其中包含一组随机日期:
{2015年1月20日、2015年2月12日、2015年2月20日、2015年6月21日、2015年7月12日、2015年7月28日、2015年7月30日、2015年9月24日、2015年12月31日}
如何按月将此阵列拆分为多个阵列?
我想要
{2015年1月20日}、{2015年2月12日、2015年2月20日}、{2015年6月21日}、{2015年7月12日、2015年7月28日、2015年7月30日}、{2015年9月24日}、{2015年12月31日}
我可以遍历整个数组,检查下一个日期是否仍在同一个月内,如果在同一个月内,则将其添加到子数组中。然而,我想知道是否有更简洁或有效的方法。
编辑:
此外,我需要按年份和月份排序,因此,例如,2014年1月15日和2015年1月23日不应合并。
下面是我提出的一种方法,但它看起来效率不高:
private void splitListByMonth(){
ArrayList<ArrayList<Homework>> mainArrayList = new ArrayList<>();
ArrayList<String> titleList = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM yyy");
for(Homework homework:mList){
calendar.setTimeInMillis(homework.getDate());
String monthString = dateFormat.format(calendar.getTime());
if(titleList.contains(monthString)){
int index = titleList.indexOf(monthString);
mainArrayList.get(index).add(homework);
} else {
titleList.add(monthString);
int index = titleList.indexOf(monthString);
mainArrayList.get(index).add(homework);
}
}
Log.d("Tag",""+titleList);
Log.d("Tag",""+mainArrayList);
}
对于Android,您应该使用Joda时间库,而不是旧的java。util。日期/。事实证明,日历类非常麻烦。请注意,Joda Time的一些替代版本已经发布,以解决最初速度较慢的Android问题。
Joda Time包含一个类YearMonth,正是我们需要将年和月表示为跟踪日期值的键。Joda Time还有一个classLocalDate
来表示一个只包含日期的值,不包含一天中的任何时间或时区。
我们使用模式
"MMMM dd yyyy"
定义了一个格式化程序来解析字符串。请注意,我们在格式化程序上指定了一个英语语言的区域设置,因此此代码将在当前默认区域设置具有英语以外的语言的JVM上成功运行。解析月份“一月”、“二月”等名称时适用比语言。
我们将LocalDate值收集为一个排序数据集,它实现了两个目的:(a)消除重复项,(b)保持日期排序。我们实现的
SortedSet
是一个TreeSet
。每个集合对象被分配给一个年-月对象。树映射跟踪哪些年月具有哪组日期。我们使用树映射而不是哈希映射来保持键的排序顺序,因为它实现了排序映射。如果您有大量的元素,并且按键排序并不重要,那么HashMap可能是更好的性能选择。
String[] input = { "January 20 2015" , "February 12 2015" , "February 20 2015" , "June 21 2015" , "July 12 2015" , "July 28 2015" , "July 30 2015" , "September 24 2015" , "December 31 2015" };
Map<YearMonth , SortedSet<LocalDate>> map = new TreeMap<>();
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MMMM dd yyyy" ).withLocale( Locale.ENGLISH );
for ( String string : input ) {
LocalDate localDate = formatter.parseLocalDate( string );
YearMonth yearMonth = new YearMonth( localDate );
if ( ! map.containsKey( yearMonth ) ) { // If this is the first encounter with such a year-month, make a new entry.
map.put( yearMonth , new TreeSet<>() );
}
map.get( yearMonth ).add( localDate );
}
转储到控制台。
System.out.println( "input: " + Arrays.toString( input ) );
System.out.println( "map: " + map );
运行时。
输入:[2015年1月20日,2015年2月12日,2015年2月20日,2015年6月21日,2015年7月12日,2015年7月28日,2015年7月30日,2015年9月24日,2015年12月31日]
地图:{2015-01=[2015-01-20],2015-02=[2015-02-12, 2015-02-20],2015-06=[2015-06-21],2015-07=[2015-07-12, 2015-07-28, 2015-07-30],2015-09=[2015-09-24],2015-12=[2015-12-31]}
在Java 8和更高版本中,您可以使用新的内置Java。时间框架。Joda Time为该框架提供了灵感。对于这个答案,代码将非常相似。
使用java 8 Collectors.groupingBy,它返回一个map,然后获取值toList。
List<List<Date>> partitions = dates.stream().collect(Collectors.groupingBy(e -> e.getYear() * 100 + e.getMonth(), TreeMap::new, Collectors.toList())).values().stream().collect(Collectors.toList());
你是在正确的轨道上,但细化年/月是一种缓慢的方法,只需跟踪年和月:
@SuppressWarnings("null")
private static List<List<Date>> splitByMonth(Date ... dates) {
List<List<Date>> datesByMonth = new ArrayList<>();
List<Date> monthList = null;
int currYear = 0, currMonth = -1;
Calendar cal = Calendar.getInstance();
for (Date date : dates) {
cal.setTime(date);
if (cal.get(Calendar.YEAR) != currYear || cal.get(Calendar.MONTH) != currMonth) {
monthList = new ArrayList<>();
datesByMonth.add(monthList);
currYear = cal.get(Calendar.YEAR);
currMonth = cal.get(Calendar.MONTH);
}
monthList.add(date);
}
return datesByMonth;
}
请注意,参数必须预先排序。在这一点上,问题评论有点不明确。
测试代码
public static void main(String[] args) throws Exception {
// Build list of all dates
String[] txtDates = { "January 20 2015", "February 12 2015", "February 20 2015", "June 21 2015",
"July 12 2015", "July 28 2015", "July 30 2015", "September 24 2015", "December 31 2015",
"January 15 2014", "January 15 2015" };
SimpleDateFormat fmt = new SimpleDateFormat("MMMM d yyyy");
Date[] allDates = new Date[txtDates.length];
for (int i = 0; i < txtDates.length; i++)
allDates[i] = fmt.parse(txtDates[i]);
// Sort dates, then split them by month
Arrays.sort(allDates);
List<List<Date>> datesByMonth = splitByMonth(allDates);
// Print result
for (List<Date> dates : datesByMonth) {
StringBuilder buf = new StringBuilder();
for (Date date : dates) {
if (buf.length() != 0)
buf.append(", ");
buf.append(fmt.format(date));
}
System.out.println(buf);
}
}
输出量
January 15 2014
January 15 2015, January 20 2015
February 12 2015, February 20 2015
June 21 2015
July 12 2015, July 28 2015, July 30 2015
September 24 2015
December 31 2015
问题内容: 这是在采访中问我的,这是我提供的解决方案: 有没有更有效的方法可以做到这一点? 编辑:更正的长度方法。 问题答案: 稍有改进,但是在主循环之后,当到达另一个输入数组的末尾时,可以用来复制其中一个输入数组的结尾。但是,那不会改变你解决方案的性能特征。
我有一个数组的值。我用一个条件对它进行排序,以保持某些项目在顶部。到目前为止,这是有效的。现在我想运行两个条件,例如,我有两个前缀要与数组中的每个项相匹配:tableprefix和第二个daryprefix。我已经实现的是将tableprefix保持在顶部。其余的项目必须按字母顺序排序。 我想要达到的目标: 1:数组项匹配表前缀在最顶部//已经实现 2:与secondaryprefix匹配的数组项
我想写一个时间O(n*lgk)的算法,将k个排序数组合并成一个排序数组,其中n是所有输入数组的元素总数。 你能告诉我怎么做吗? 编辑:我编写了以下算法: 你能告诉我这是否正确吗?
这就是我的问题。我需要帮助,试图找出我做错了什么,并从那里开始。我需要创建一个运行这些指令的程序。 创建名为Fraction的java类。该类用于表示两个整数的比率。包括允许用户设置分子和分母的突变体方法。还包括在屏幕上显示分数作为配给(例如5/9)的方法。此方法不需要将分数降低到最低项。 分数类应包含以下内容: •用于存储分子、分母和比值的私有实例变量。 •设置所有实例变量的构造函数。 •获取和
问题内容: 我有一个带有数字值的字符串键数组,可用于具有每个标签出现次数的标签列表中,因此: 这是为了我可以按降序显示标签列表,因此: 我可以使用 arsort 通过出色的值进行反向排序,但是我还希望具有相同数字值的所有标签都按字母顺序排序,因此最终结果可以是: 有办法可以做到吗?我猜想 usort 可能是要走的路,但是我看了php.net上的示例,我的眼睛呆呆了!非常感谢!!! 问题答案: 看一
假设我有两个NumPy数组 我希望根据中的值,将数组有效地拆分为子数组。 我想要的输出是 假设以零开始并按升序排序,那么最有效的方法是什么? 注意:这个问题是这个问题的排序版本:根据另一个数组的值(未排序,而是分组)将NumPy数组拆分为子数组