如何使用guava创建一个不可变的日期列表(java.util.Date)?
我有这个片段:
Date date = new GregorianCalendar(2014, 4, 1).getTime();
// doesn't work:
// List<Date> immutableList = ImmutableList.of(date);
// doesn't work either:
List<Date> immutableList = ImmutableList.copyOf(new Date[] { date });
date.setMonth(3);
System.out.println("immutableList has: " + immutableList.get(0));
而我想让它成为一个真正的&#34;不可变列表,以便在更改date
对象时不会更改第0个元素。
答案 0 :(得分:7)
正如您已经发现的那样,使用不可变列表可以保护列表不被修改,但不会保护列表中包含的元素。为此,元素本身必须是不可变的。
不幸的是,它无法创建不可变的java.util.Date
对象。您可以考虑几种方法:
java.util.Date
类型的对象是可变的,但java.lang.Long
类型的对象是不可变的
因此,您可以创建一个Long
个对象的不可变列表来存储从调用Date.getTime()
获得的long
值,并在检索时使用Date(long date)
构造函数动态构造新的日期对象从列表中。答案 1 :(得分:1)
List.of
和List.copyOf
分别产生不可修改的List
实现。Date
或Calendar
。
示例:
List.copyOf( // Produce an unmodifiable `List` based on elements drawn from another `Collection` in iteration-order.
LocalDate.of( 2014 , Month.MARCH , 1 ) // Modern class to represent a date-only value, without time-of-day and without time zone.
.datesUntil( // Generates a stream of `LocalDate` objects, incrementing one day at a time.
LocalDate.of( 2014 , Month.APRIL , 1 ) // The `LocalDate` class is designed to produce immutable objects, with state that can be read but not altered (not “mutated”).
) // Returns a `Stream<LocalDate>`.
.collect( // Processes the series of dates coming from the stream.
Collectors.toCollection( ArrayList :: new ) // Creates a `List`, and adds the series of dates to that list.
) // Returns a `List<LocalDate>`.
) // Returns another `List<LocalDate>` whose elements cannot be added, dropped, or replaced from the collection.
.toString() // Generates a `String` with text representing the value of each contained `LocalDate` object.
[2014-03-01、2014-03-02、2014-03-03、2014-03-04、2014-03-05、2014-03-06、2014-03-07、2014-03- 08、2014-03-09、2014-03-10、2014-03-11、2014-03-12、2014-03-13、2014-03-14、2014-03-15、2014-03-16, 2014-03-17、2014-03-18、2014-03-19、2014-03-20、2014-03-21、2014-03-22、2014-03-23、2014-03-24、2014- 2014年3月25日,2014-03-26、2014-03-27、2014-03-28、2014-03-29、2014-03-30、2014-03-31]
Google Guava库在许多方面都非常有用。但是,不再需要为一系列日期实现只读数据结构的目标。 Java现在具有支持此功能的内置功能。</ p>
现代方法使用 java.time 类代替了可怕的旧日期时间类,例如Date
和Calendar
。
LocalDate
LocalDate
类表示没有日期和时区的仅日期值。
您的问题不清楚。似乎您想要的是上个月的日期列表。
LocalDate stop = LocalDate.of( 2014 , Month.APRIL , 1 ) ; // Sane numbering: `2014` is the year 2014, and 1-12 = Jan-Dec.
LocalDate start = stop.minusMonths( 1 ) ;
您可以使用Java Streams工具来生成一系列LocalDate
对象。首先创建一个Stream< LocalDate >
。
Stream< LocalDate > streamOfLocalDates = start.datesUntil( stop ) ;
然后,将从该流发出的一系列LocalDate
对象收集到List
集合中。
List< LocalDate > localDates =
streamOfLocalDates.collect(
Collectors.toCollection( ArrayList::new )
)
;
上面产生的List
是可修改的,这意味着我们可以添加,删除或替换其元素。为了防止对List
进行此类更改,请使用Java 10及更高版本中的新List
功能,生成另一个List
,这是不可修改的List.copyOf
。
List< LocalDate > localDatesUnmodifiable =
List.copyOf(
localDates
)
;
我们在这里设有两个级别的保护措施,以防止数据发生更改。
List.copyOf
可防止您在列表中添加,删除或替换元素。它并不能阻止您修改存储在每个元素中的对象的内部状态。 因此List.copyOf( List< LocalDate > )
的元素或内容(完全是只读的数据结构)都无法修改。
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 2 :(得分:0)
没办法。如果您确实想使用Date
,则必须克隆每个get()
结果以保护存储的值。你还必须克隆你输入的日期,除非你确定它们之后不会改变。
您可以做的最好的事情是切换到某种不可变的数据类型。否则,你必须包装所有访问,这是一个真正的痛苦。您可以将List
设置在long[]
上(这可能比调整列表更不容易出错,因为不会错误地发布存储对象)。
答案 3 :(得分:0)
如果您别无选择,只能使用Date对象,那么您始终可以返回date对象的副本。这将使您的对象不可变。
public final class ImmutableDates{
private final List<Date> dates;
// other final fields
// constructor with final dates and other final fields as argument
// don't expose setter
// always create and return a new list populated with new dates
public List<Date> getDates() {
List<Date> newDates = dates.stream().map(p -> new Date(p.getTime())).collect(Collectors.toList());
return newDates;
}
}
始终创建并返回填充有新日期的新列表