tl;博士
Schedule.daysForGroupOnDate(
Group.D ,
LocalDate.now()
)
这种方法产生了一个新的结果
Set
DayOfWeek
DayOfWeek.TUESDAY
&
DayOfWeek.THURSDAY
现代爪哇
有人能提出一个很酷的方法吗?
对
这个
java.time
Java内置的框架提供了
Month
DayOfWeek
EnumSet
和
EnumMap
提供的实现
Set
Map
优化后可与枚举一起使用,以便在非常少的内存中快速执行。
你可以定义你自己的
enums
Oracle Tutorial
.
定义自己的枚举的简单语法实际上提供了解决此问题所需的许多功能,消除了一些复杂的编码。刚出现的
literals syntax
对于中的集合和贴图
collections factory methods
在Java9中(
JEP 269
这里是一个完整的工作应用程序。
注意代码是多么少
对于算法来说,这是非常困难的。定义自己的自定义枚举完成了大部分繁重的工作。
此应用程序代码有一个警告:它假设您的业务定义没有任何更改,或者至少如果您只关心当前规则的更改,则最新的更改是最大的。如果您的规则随着时间的推移而改变,并且您需要表示所有过去、现在和将来的版本,我将构建一个非常不同的应用程序,可能有一个数据库来存储规则。但是这个应用程序解决了这个问题。
Season
将您的季节表示为枚举
季
. 每个季节对象都有一个
List
月
枚举定义特定季节长度的对象。新的
List.of
package com.basilbourque.watering;
import java.time.LocalDate;
import java.time.Month;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
public enum Season
{
SPRING( List.of( Month.MARCH , Month.APRIL ) ),
SUMMER( List.of( Month.MAY , Month.JUNE, Month.JULY , Month.AUGUST ) ),
FALL( List.of( Month.SEPTEMBER , Month.OCTOBER ) ),
WINTER( List.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY ) );
private List< Month > months;
// Constructor
Season ( List < Month > monthsArg )
{
this.months = monthsArg;
}
public List < Month > getMonths ( )
{
return this.months;
}
// For any given month, determine the season.
static public Season ofLocalMonth ( Month monthArg )
{
Season s = null;
for ( Season season : EnumSet.allOf( Season.class ) )
{
if ( season.getMonths().contains( monthArg ) )
{
s = season;
break; // Bail out of this FOR loop.
}
}
return s;
}
// For any given date, determine the season.
static public Season ofLocalDate ( LocalDate localDateArg )
{
Month month = localDateArg.getMonth();
Season s = Season.ofLocalMonth( month );
return s;
}
// Run `main` for demo/testing.
public static void main ( String[] args )
{
// Dump all these enum objects to console.
for ( Season season : EnumSet.allOf( Season.class ) )
{
System.out.println( "Season: " + season.toString() + " = " + season.getMonths() );
}
}
}
Group
将每组客户草坪/庭院(A、B、C、D、E)表示为一个名为
组
,映射
季
设置
属于
枚举对象。例如
Group.A
在里面
Season.SPRING
允许在两天内浇水,
&
星期四
.
package com.basilbourque.watering;
import java.time.DayOfWeek;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
public enum Group
{
A(
Map.of(
Season.SPRING , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
Season.WINTER , EnumSet.of( DayOfWeek.TUESDAY )
)
),
B(
Map.of(
Season.SPRING , EnumSet.of( DayOfWeek.FRIDAY ) ,
Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.FRIDAY ) ,
Season.WINTER , EnumSet.of( DayOfWeek.FRIDAY )
)
),
C(
Map.of(
Season.SPRING , EnumSet.of( DayOfWeek.MONDAY ) ,
Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
Season.FALL , EnumSet.of( DayOfWeek.MONDAY , DayOfWeek.TUESDAY ) ,
Season.WINTER , EnumSet.of( DayOfWeek.MONDAY )
)
),
D(
Map.of(
Season.SPRING , EnumSet.of( DayOfWeek.WEDNESDAY , DayOfWeek.FRIDAY ) ,
Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
Season.FALL , EnumSet.of( DayOfWeek.FRIDAY ) ,
Season.WINTER , EnumSet.of( DayOfWeek.WEDNESDAY )
)
),
E(
Map.of(
Season.SPRING , EnumSet.of( DayOfWeek.TUESDAY ) ,
Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY ) ,
Season.WINTER , EnumSet.of( DayOfWeek.WEDNESDAY )
)
);
private Map < Season, Set < DayOfWeek > > map;
// Constructor
Group ( Map < Season, Set < DayOfWeek > > mapArg )
{
this.map = mapArg;
}
// Getter
private Map < Season, Set < DayOfWeek > > getMapOfSeasonToDaysOfWeek() {
return this.map ;
}
// Retrieve the DayOfWeek set for this particular Group.
public Set<DayOfWeek> daysForSeason (Season season ) {
Set<DayOfWeek> days = this.map.get( season ) ; // Retrieve the value (set of days) for this key (a season) for this particular grouping of lawns/yards.
return days;
}
// Run `main` for demo/testing.
public static void main ( String[] args )
{
// Dump all these enum objects to console.
for ( Group group : EnumSet.allOf( Group.class ) )
{
System.out.println( "Group: " + group.toString() + " = " + group.getMapOfSeasonToDaysOfWeek() );
}
}
}
Schedule
把所有这些都放在一起
班
此类使用上面定义的两个枚举来完成有用的工作。到目前为止实现的唯一方法告诉您在特定日期允许特定组在一周中的哪几天。该方法确定
申请该日期。
运行
main
方法转储我们两个枚举的内容,并报告一周中的几天,允许每组为特定的硬编码日期浇水。
package com.basilbourque.watering;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
import java.util.EnumSet;
import java.util.Set;
public class Schedule
{
static private DateTimeFormatter isoWeekFormatter = DateTimeFormatter.ofPattern( "uuuu-'W'ww" ) ;
static public Set < DayOfWeek > daysForGroupOnDate ( Group group , LocalDate localDate )
{
Season season = Season.ofLocalDate( localDate );
Set < DayOfWeek > days = group.daysForSeason( season );
return days;
}
// Run `main` for demo/testing.
public static void main ( String[] args )
{
Season.main( null );
Group.main( null );
// Dump all these enum objects to console.
for ( Group group : EnumSet.allOf( Group.class ) )
{
LocalDate localDate = LocalDate.now( ZoneId.of( "Africa/Tunis" ) );
Set < DayOfWeek > days = Schedule.daysForGroupOnDate( group , localDate );
String week = localDate.format( Schedule.isoWeekFormatter ) ; // Standard ISO 8601 week, where week number one has the first Thursday of the calendar year, and week starts on Monday, so year is either 52 or 53 weeks long.
String message = "Group " + group + " â Watering days on " + localDate + " week # " + week + " is: " + days;
System.out.println( message );
}
}
}
跑步时
Schedule.main
,我们看到它被转储到控制台。
季节:春季=[三月、四月]
季节:秋季=[九月、十月]
季节:冬季=[11月、12月、1月、2月]
组:A={春季=[周二,周四],秋季=[周二,周四],夏季=[周一,周二,周三,周四,周五,周六,周日],冬季=[周二]}
B组{春季=[星期五],秋季=[星期二,星期五],夏季=[星期一,星期二,星期三,星期四,星期五,星期六,星期日],冬季=[星期五]}
组:D={春季=[星期三,星期五],秋季=[星期五],夏季=[星期一,星期二,星期三,星期四,星期五,星期六,星期日],冬季=[星期三]}
小组:E={春季=[星期二],秋季=[星期二,星期三],夏季=[星期一,星期二,星期三,星期四,星期五,星期六,星期日],冬季=[星期三]}
2018-01-30周A组浇水日#2018-W05为:[周二]
B组2018-01-30周的浇水日#2018-W05为:[周五]
C组2018-01-30周的浇水日#2018-W05为:[周一]
D组2018-01-30周的浇水日#2018-W05为:[周三]
E组2018-01-30周的浇水日#2018-W05为:[周三]
ISO 8601每周
您可能会发现了解
ISO 8601
definition of week
. 该标准给出了周的具体含义,并定义了表示该周内某一周或某一天的文本格式。
在java中使用这些星期,请考虑添加
ThreeTen-Extra
库到您的项目中,以利用
YearWeek
班
LocalDate
LocalDate
类表示一个仅限日期的值,该值不包含一天中的时间,也不包含时区。
时区对于确定日期至关重要。在任何一个特定的时刻,世界各地的日期都因地区而异。例如,午夜后几分钟
Paris France
新的一天还在昨天吗
Montréal Québec
指定一个
proper time zone name
continent/region
例如
America/Montreal
,
Africa/Casablanca
Pacific/Auckland
EST
IST
事实上
不
真正的时区,没有标准化,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
ZoneId z = ZoneId.systemDefault() ; // Get JVMâs current default time zone.
或者指定一个日期。你可以用一个数字来设置月份,1-12月的数字为1-12。
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
月
枚举对象是预定义的,一年中每个月一个。提示:使用这些
月
对象,而不仅仅是一个整数,以使代码更具自文档性,确保有效值,并提供
type-safety
.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
不变集合
上面看到的列表、集合和映射在理想情况下应该是不可变的集合,因为更改这些集合的成员身份可能会混淆和错误。
Map.of
已经承诺是不变的。然而,在我们的案例中
地图
理想情况下应该是一个
枚举图
为了提高性能和内存效率。目前的执行情况
地图
Set.of
显然,不检测枚举作为成员的使用,而是通过内部使用
和
. 有一个OpenJDK问题开始考虑这样的问题:
consider enhancements to EnumMap and EnumSet
.
获取不可变EnumSet和不可变EnumMap的一种方法是通过
Google Guava
图书馆:
每次使用的结果都有一个基础
枚举集
/
枚举图
. 操作,例如
get
和
put
抛出异常。因此,您可以获得与枚举相关的优化以及不变性。
季
和
组
不变性
package com.basilbourque.watering;
import java.time.LocalDate;
import java.time.Month;
import java.util.EnumSet;
import java.util.List;
public enum Season
{
SPRING( List.of( Month.MARCH , Month.APRIL ) ), // `List.of` provides literals-style syntax, and returns an immutable `List`. New in Java 9.
SUMMER( List.of( Month.MAY , Month.JUNE, Month.JULY , Month.AUGUST ) ),
FALL( List.of( Month.SEPTEMBER , Month.OCTOBER ) ),
WINTER( List.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY ) );
private List< Month > months;
// Constructor
Season ( List < Month > monthsArg )
{
this.months = monthsArg;
}
public List < Month > getMonths ( )
{
return this.months;
}
// For any given month, determine the season.
static public Season ofLocalMonth ( Month monthArg )
{
Season s = null;
for ( Season season : EnumSet.allOf( Season.class ) )
{
if ( season.getMonths().contains( monthArg ) )
{
s = season;
break; // Bail out of this FOR loop.
}
}
return s;
}
// For any given date, determine the season.
static public Season ofLocalDate ( LocalDate localDateArg )
{
Month month = localDateArg.getMonth();
Season s = Season.ofLocalMonth( month );
return s;
}
// Run `main` for demo/testing.
public static void main ( String[] args )
{
// Dump all these enum objects to console.
for ( Season season : EnumSet.allOf( Season.class ) )
{
System.out.println( "Season: " + season.toString() + " = " + season.getMonths() );
}
}
}
package com.basilbourque.watering;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.time.DayOfWeek;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
public enum Group
{
A(
Maps.immutableEnumMap(
Map.of( // `Map.of` provides literals-style syntax, and returns an immutable `Map`. New in Java 9.
Season.SPRING , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
Season.FALL , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
Season.WINTER , Sets.immutableEnumSet( DayOfWeek.TUESDAY )
)
)
),
B(
Maps.immutableEnumMap(
Map.of(
Season.SPRING , Sets.immutableEnumSet( DayOfWeek.FRIDAY ) ,
Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
Season.FALL , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.FRIDAY ) ,
Season.WINTER , Sets.immutableEnumSet( DayOfWeek.FRIDAY )
)
)
),
C(
Maps.immutableEnumMap(
Map.of(
Season.SPRING , Sets.immutableEnumSet( DayOfWeek.MONDAY ) ,
Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
Season.FALL , Sets.immutableEnumSet( DayOfWeek.MONDAY , DayOfWeek.TUESDAY ) ,
Season.WINTER , Sets.immutableEnumSet( DayOfWeek.MONDAY )
)
)
),
D(
Maps.immutableEnumMap(
Map.of(
Season.SPRING , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY , DayOfWeek.FRIDAY ) ,
Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
Season.FALL , Sets.immutableEnumSet( DayOfWeek.FRIDAY ) ,
Season.WINTER , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY )
)
)
),
E(
Maps.immutableEnumMap(
Map.of(
Season.SPRING , Sets.immutableEnumSet( DayOfWeek.TUESDAY ) ,
Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
Season.FALL , Sets.immutableEnumSet( EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY ) ) ,
Season.WINTER , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY )
)
)
);
private Map < Season, Set < DayOfWeek > > map;
// Constructor
Group ( Map < Season, Set < DayOfWeek > > mapArg )
{
this.map = mapArg;
}
// Getter
private Map < Season, Set < DayOfWeek > > getMapOfSeasonToDaysOfWeek ( )
{
return this.map;
}
// Retrieve the DayOfWeek set for this particular Group.
public Set < DayOfWeek > daysForSeason ( Season season )
{
Set < DayOfWeek > days = this.map.get( season ); // Retrieve the value (set of days) for this key (a season) for this particular grouping of lawns/yards.
return days;
}
// Run `main` for demo/testing.
public static void main ( String[] args )
{
// Dump all these enum objects to console.
for ( Group group : EnumSet.allOf( Group.class ) )
{
System.out.println( "Group: " + group.toString() + " = " + group.getMapOfSeasonToDaysOfWeek() );
}
}
}
关于java.time
这个
java.time
legacy
日期时间类,例如
java.util.Date
,
Calendar
SimpleDateFormat
.
这个
Joda-Time
项目,现在在
maintenance mode
,建议迁移到
上课。
要了解更多信息,请参阅
Oracle Tutorial
. 并搜索堆栈溢出以获得许多示例和解释。规格是
JSR 310
.
从哪里获得java.time类?
这个
ThreeTen-Extra
project使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。您可以在这里找到一些有用的类,例如
Interval
,
年鉴
,
YearQuarter
和
more