我需要表示以下数据(用Java):
我正在考虑使用 TreeMap,但不知道如何使用。有什么想法吗?
注意事项,假设您对管理日历条目感兴趣:
模型
// best to use ENUM for fixed set of constants
enum Month {
JANUARY, FEBRUARY, ... , NOVEMBER, DECEMBER
}
enum Weekday {
SUNDAY, MONDAY, ... , FRIDAY, SATURDAY
}
/**
* The day "data node". Fill in constructors/accessors.
*/
class Day {
int year;
Month month;
Weekday weekday;
String date; // hashkey
String entry; // the entry
}
/**
* The calendar, simply mapping a unique date to it's day.
* Create a date like: year + "-" + MONTH + "-" + DAY
*/
HashMap<String, Day> calendar;
Month
和 DayOfWeek
。
景色
由于我们的数据结构并不稀疏,因此独立视图必须模拟完整的日历。根据日历的规则显示所有日期/生成所有日期,但如果保存新条目,则仅在
HashMap
中添加一天。
注释
HashMap
包装在一个类中以仲裁 days
上的 CRUD操作。
month
中,或删除 year
,考虑在上面放置一个像 year => month => day
这样的三级地图。Swing 中的 JTree 也可以用作数据结构。
但是您应该问自己的第一个问题是“我想如何访问数据”。
您需要某种树结构。 这可能是您的起点:
public class Node {
private String label;
private List<Node> children;
//add Constructors, getters, setters, and member methods, etc
}
Node root = new Node();
root.setLabel("2012");
//children of root are "01", "02", etc.
将模型数据与视图数据明确分开。
这是一个与佩斯利答案中提出的模型不同的模型。
Map<Calendar, String> thisIsAllYouNeedForTheModel = new HashMap<Calendar, String>();
Calendar thisIsTheKey = Calendar.getInstance();
thisIsTheKey.clear();
thisIsTheKey.set(Calendar.YEAR, theYear);
thisIsTheKey.set(Calendar.MONTH, theMonth);
thisIsTheKey.set(Calendar.DAY_OF_MONTH, theMonth);
thisIsTheKey.set(Calendar.HOUR, theHour);
thisIsTheKey.set(Calendar.MINUTE, theMinute);
thisIsTheKey.set(Calendar.SECOND, theSecond);
thisIsAllYouNeedForTheModel.put(thisIsTheKey, data);
编辑:我傻了。
Map<Calendar, String>
是我的建议。
SequencedMap < LocalDate , String > map = new TreeMap<>() ;
map.put( LocalDate.of( 2012 , Month.JANUARY , 1 ) , "Hello I am a string" ) ;
在 Java 8+ 中,使用现代的 java.time 类取代了存在严重缺陷的遗留日期时间类。
LocalDate
。一个月,使用 Month
枚举。
将每个日期映射到其文本片段。通过 Oracle 免费提供的本教程了解有关 Java 集合框架中的映射的信息。
SequencedMap
Map
没有遭遇顺序。所以在现代 Java 中,使用
SequencedMap
接口。在旧版 Java 中使用 NavigableMap
。在古老的 Java 中,使用
SortedMap
。与 Java 实现
SequencedMap
捆绑在一起的三个类:
ConcurrentSkipListMap
、
LinkedHashMap
、
TreeMap
。根据您的需求,如果不是多线程,请使用 TreeMap
作为选择的实现。
SequencedMap < LocalDate , String > map = new TreeMap<>() ;
要了解 Java 21+ 中的顺序集合,请参阅 Nicolai Parlog 的视频、官方文档 JEP 431:顺序集合 和 Stuart Marks 的演讲。
添加您的条目。
LocalDate ld = LocalDate.of( 2012 , Month.JANUARY , 1 ) ; // 2012-01-01.
map.put( ld , "Hello I am a string" ) ;
检索:
String s = map.get( ld ) ; // Retrieve the string value for this `LocalDate` key.
层次结构此方法循环遍历
SequencedMap
以查看键,在本例中为所有
LocalDate
值。我们得到了一个不同的年份排序列表,使用
Year
类表示。然后,对于这些年份中的任何一年,我们都可以获得一个不同的排序月份列表,由 Month
枚举表示。最后,对于任何月份(和年份),我们都可以通过 auto-boxing 获得表示为 Integer
对象的不同排序的月份数字列表。
这种方法很简单,但效率不高。由于代码简单(基本上都是单行代码!),我确实会选择这种方法用于数据量较小的生产用途。对于大量数据,您将需要不同的方法。
这是我们用于表示年-月-日-字符串层次结构的类。
package work.basil.example.hierarchy;
import java.time.LocalDate;
import java.time.Month;
import java.time.Year;
import java.time.YearMonth;
import java.util.SequencedCollection;
import java.util.SequencedMap;
import java.util.TreeMap;
public class YearMonthDayStringHierarchy
{
private final SequencedMap < LocalDate, String > map = new TreeMap <>( );
public String put ( final LocalDate localDate , final String string ) { return map.put( localDate , string ); }
public String get ( final LocalDate localDate ) { return map.get( localDate ); }
public String get ( final Year year , final Month month , final Integer day ) { return map.get( LocalDate.of( year.getValue( ) , month , day ) ); } // Convenience method.
public SequencedCollection < Year > years ( )
{
return this
.map
.sequencedKeySet( )
.stream( )
.map( Year :: from )
.distinct( )
.sorted( )
.toList( );
}
SequencedCollection < Month > monthsForYear ( final Year year )
{
return this
.map
.sequencedKeySet( )
.stream( )
.filter( localDate -> Year.from( localDate ).equals( year ) )
.map( Month :: from )
.distinct( )
.sorted( )
.toList( )
;
}
SequencedCollection < Integer > daysForYearMonth ( final Year year , final Month month )
{
final YearMonth yearMonth = YearMonth.of( year.getValue( ) , month ); // Odd that `YearMonth` has no `of` factory method taking `Year` object. So extract primitive year number.
return this
.map
.sequencedKeySet( )
.stream( )
.filter( localDate -> YearMonth.from( localDate ).equals( yearMonth ) )
.map( LocalDate :: getDayOfMonth )// Auto-boxed to Integer.
.distinct( )
.sorted( )
.toList( )
;
}
}
这是一个用于练习该代码的示例应用程序。
package work.basil.example.hierarchy;
import java.time.LocalDate;
import java.time.Month;
import java.time.Year;
import java.time.ZoneId;
public class YearMonthDayStringHierarchyApp
{
public static void main ( String[] args )
{
YearMonthDayStringHierarchyApp app = new YearMonthDayStringHierarchyApp( );
app.demo( );
}
private void demo ( )
{
YearMonthDayStringHierarchy map = new YearMonthDayStringHierarchy( );
LocalDate v2012_01_01 = LocalDate.of( 2012 , Month.JANUARY , 1 ); // 2012-01-01.
map.put( v2012_01_01 , "Hello I am a string" );
LocalDate today = LocalDate.now( ZoneId.of( "America/Edmonton" ) );
map.put( today , "Today is " + today + "." );
LocalDate yesterday = today.minusDays( 1 );
map.put( yesterday , "Yesterday is " + yesterday + "." );
for ( Year year : map.years( ) )
{
System.out.println( year );
for ( Month month : map.monthsForYear( year ) )
{
System.out.println( " ".repeat( 4 ) + month );
for ( Integer day : map.daysForYearMonth( year , month ) )
{
System.out.println( " ".repeat( 8 ) + day );
System.out.println( " ".repeat( 12 ) + map.get( year , month , day ) );
}
}
}
}
}
运行时:
2012
JANUARY
1
Hello I am a string
2024
AUGUST
28
Yesterday is 2024-08-28.
29
Today is 2024-08-29.
SequencedMap
,对
.sorted
的调用可能是不必要的。我考虑得不够仔细,也没有测试过他们的遗漏。
for
循环,如下所示。但我认为这更难读。
map.years( ).forEach( year -> {
System.out.println( year );
map.monthsForYear( year ).forEach( month -> {
System.out.println( " ".repeat( 4 ) + month );
map.daysForYearMonth( year , month ).forEach( day -> {
System.out.println( " ".repeat( 8 ) + day );
System.out.println( " ".repeat( 12 ) + map.get( year , month , day ) );
} );
} );
} );