今天记录一道笔试题
1.原题:
需求:
股票交易或者分析会涉及到交易日的查询,为了分析高效快速,通常会把交易日放到内存中。要求实现下面的接口。
interface TradingDayService {
//判断是否为交易日
boolean isTradingDay(LocalDate date);
//查询下一个交易日
Optional<LocalDate> queryNextTradingDay(LocalDate date);
//查询一段时间范围的交易日, 注意包括[from, to]
List<LocalDate> queryBetween(LocalDate from, LocalDate to);
//查询日期所属月份的第一个交易日
Optional<LocalDate> queryFirstTradingDayOfMonth(LocalDate date)
}
要求如下:
1 请用Java,Scala,Kotlin任意一种语言实现。
2. 访问速度足够快。
3. 尽量少占内存。
4. 有单元测试。
2.样本:(这里我只是列举了部分数据,完整的数据是一整年的数据。)
“2020-01-02”, “2020-01-03”, “2020-01-06”, “2020-01-07”, “2020-01-08”, “2020-01-09”, “2020-01-10”, “2020-01-13”, “2020-01-14”, “2020-01-15”, “2020-01-16”, “2020-01-17”, “2020-01-20”, “2020-01-21”, “2020-01-22”, “2020-01-23”, “2020-02-03”, “2020-02-04”, “2020-02-05”, “2020-02-06”, “2020-02-07”, “2020-02-10”, “2020-02-11”, “2020-02-12”, “2020-02-13”, “2020-02-14”, “2020-02-17”, “2020-02-18”, “2020-02-19”, “2020-02-20”, “2020-02-21”, “2020-02-24”, “2020-02-25”, “2020-02-26”, “2020-02-27”, “2020-02-28”, “2020-03-02”, “2020-03-03”, “2020-03-04”, “2020-03-05”, “2020-03-06”, “2020-03-09”, “2020-03-10”, “2020-03-11”, “2020-03-12”, “2020-03-13”, “2020-03-16”, “2020-03-17”, “2020-03-18”, “2020-03-19”, “2020-03-20”, “2020-03-23”, “2020-03-24”, “2020-03-25”, “2020-03-26”, “2020-03-27”, “2020-03-30”, “2020-03-31”, “2020-04-01”, “2020-04-02”, “2020-04-03”, “2020-04-07”, “2020-04-08”, “2020-04-09”, “2020-04-10”, “2020-04-13”。
3.解决思路:
(1)找数据规律
我们首先观察每个月的数据,查看交易日样本数据是否有规律。可以发现,毫无规律可言。。。
(2)认真阅读需求,提炼要点
读题,看要求,要求主要有两点:速度快、占内存少。任务就是实现这个TradingDayService接口的四个方法。看接口的参数、发现主要是对LocalDate运用的考察。
(3)如何存储样本数据:
第一种:交易日数据主要是用于查询,变动情况很好,考虑到要占用内存少,其实我们可以把这些样本数据存入redis里(实际开发用的比较多)。
第二种:使用一个单例来存储数据,该样本数据就只会占用一块内存空间。(其实在实际开发中,单例专门用于存储数据的情况很少,除非要用到该数据的多个处理方法,才会使用单例封装该数据和处理方法)
第三种:直接使用一个静态的集合,来存储。
采用:因为题目中,没有说明可以使用redis,所有我个人采用了单例模式来存储该数据。数据的存储,大家根据实际的需求来看。
5.话不多说,直接上代码
单例类
package singleton;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TradingDayDataSingleton {
private List<String> tradingDayData = Arrays.asList("2020-01-02", "2020-01-03", "2020-01-06", "2020-01-07", "2020-01-08", "2020-01-09", "2020-01-10", "2020-01-13", "2020-01-14", "2020-01-15", "2020-01-16", "2020-01-17", "2020-01-20", "2020-01-21", "2020-01-22", "2020-01-23",
"2020-02-03", "2020-02-04", "2020-02-05", "2020-02-06", "2020-02-07", "2020-02-10", "2020-02-11", "2020-02-12", "2020-02-13", "2020-02-14", "2020-02-17", "2020-02-18", "2020-02-19", "2020-02-20", "2020-02-21", "2020-02-24", "2020-02-25",
"2020-02-26", "2020-02-27", "2020-02-28", "2020-03-02", "2020-03-03", "2020-03-04", "2020-03-05", "2020-03-06", "2020-03-09", "2020-03-10", "2020-03-11", "2020-03-12", "2020-03-13", "2020-03-16", "2020-03-17", "2020-03-18", "2020-03-19",
"2020-03-20", "2020-03-23", "2020-03-24", "2020-03-25", "2020-03-26", "2020-03-27", "2020-03-30", "2020-03-31", "2020-04-01", "2020-04-02", "2020-04-03", "2020-04-07", "2020-04-08", "2020-04-09", "2020-04-10", "2020-04-13", "2020-04-14",
"2020-04-15", "2020-04-16", "2020-04-17", "2020-04-20", "2020-04-21", "2020-04-22", "2020-04-23", "2020-04-24", "2020-04-27", "2020-04-28", "2020-04-29", "2020-04-30", "2020-05-06", "2020-05-07", "2020-05-08", "2020-05-11", "2020-05-12",
"2020-05-13", "2020-05-14", "2020-05-15", "2020-05-18", "2020-05-19", "2020-05-20", "2020-05-21", "2020-05-22", "2020-05-25", "2020-05-26", "2020-05-27", "2020-05-28", "2020-05-29", "2020-06-01", "2020-06-02", "2020-06-03", "2020-06-04",
"2020-06-05", "2020-06-08", "2020-06-09", "2020-06-10", "2020-06-11", "2020-06-12", "2020-06-15", "2020-06-16", "2020-06-17", "2020-06-18", "2020-06-19", "2020-06-22", "2020-06-23", "2020-06-24", "2020-06-29", "2020-06-30", "2020-07-01",
"2020-07-02", "2020-07-03", "2020-07-06", "2020-07-07", "2020-07-08", "2020-07-09", "2020-07-10", "2020-07-13", "2020-07-14", "2020-07-15", "2020-07-16", "2020-07-17", "2020-07-20", "2020-07-21", "2020-07-22", "2020-07-23", "2020-07-24",
"2020-07-27", "2020-07-28", "2020-07-29", "2020-07-30", "2020-07-31", "2020-08-03", "2020-08-04", "2020-08-05", "2020-08-06", "2020-08-07", "2020-08-10", "2020-08-11", "2020-08-12", "2020-08-13", "2020-08-14", "2020-08-17", "2020-08-18",
"2020-08-19", "2020-08-20", "2020-08-21", "2020-08-24", "2020-08-25", "2020-08-26", "2020-08-27", "2020-08-28", "2020-08-31", "2020-09-01", "2020-09-02", "2020-09-03", "2020-09-04", "2020-09-07", "2020-09-08", "2020-09-09", "2020-09-10",
"2020-09-11", "2020-09-14", "2020-09-15", "2020-09-16", "2020-09-17", "2020-09-18", "2020-09-21", "2020-09-22", "2020-09-23", "2020-09-24", "2020-09-25", "2020-09-28", "2020-09-29", "2020-09-30", "2020-10-09", "2020-10-12", "2020-10-13",
"2020-10-14", "2020-10-15", "2020-10-16", "2020-10-19", "2020-10-20", "2020-10-21", "2020-10-22", "2020-10-23", "2020-10-26", "2020-10-27", "2020-10-28", "2020-10-29", "2020-10-30", "2020-11-02", "2020-11-03", "2020-11-04", "2020-11-05",
"2020-11-06", "2020-11-09", "2020-11-10", "2020-11-11", "2020-11-12", "2020-11-13", "2020-11-16", "2020-11-17", "2020-11-18", "2020-11-19", "2020-11-20", "2020-11-23", "2020-11-24", "2020-11-25", "2020-11-26", "2020-11-27", "2020-11-30",
"2020-12-01", "2020-12-02", "2020-12-03", "2020-12-04", "2020-12-07", "2020-12-08", "2020-12-09", "2020-12-10", "2020-12-11", "2020-12-14", "2020-12-15", "2020-12-16", "2020-12-17", "2020-12-18", "2020-12-21", "2020-12-22", "2020-12-23",
"2020-12-24", "2020-12-25", "2020-12-28", "2020-12-29", "2020-12-30", "2020-12-31");
private TradingDayDataSingleton() {}
private static class TradingDayData {
private static final TradingDayDataSingleton instance = new TradingDayDataSingleton();
}
public static TradingDayDataSingleton getInstance(){
return TradingDayData.instance;
}
public List<String> getTradingDayData() {
return tradingDayData;
}
public void setTradingDayData(List<String> tradingDayData) {
this.tradingDayData = tradingDayData;
}
/**
* 把所有的交易日字符串类型转换为LocalDate类型
* @return
*/
public List<LocalDate> tradingDaysString2LocalDate() {
List<LocalDate> localDates = new ArrayList<>();
List<String> tradingDayData = getTradingDayData();
tradingDayData.forEach(t->{
LocalDate localDate = LocalDate.parse(t);
localDates.add(localDate);
});
return localDates;
}
}
接口类
public interface TradingDayService {
//判断是否为交易日
boolean isTradingDay(LocalDate date);
//查询下一个交易日
Optional<LocalDate> queryNextTradingDay(LocalDate date);
//查询一段时间范围的交易日, 注意包括[from, to]
List<LocalDate> queryBetween(LocalDate from, LocalDate to);
//查询日期所属月份的第一个交易日
Optional<LocalDate> queryFirstTradingDayOfMonth(LocalDate date);
}
接口实现类
public class TradingDayServiceImpl implements TradingDayService {
@Override
public boolean isTradingDay(LocalDate date) {
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String day = format.format(date);
List<String> allTradingDay = TradingDayDataSingleton.getInstance().getTradingDayData();
return allTradingDay.contains(day);
}
@Override
public Optional<LocalDate> queryNextTradingDay(LocalDate date) {
//下一天日期
LocalDate nextDay = date.plusDays(1L);
//哨兵,防止死循环
int flag = 0;
while (true) {
//判断下一天是否是交易日
boolean tradingDay = this.isTradingDay(nextDay);
if (tradingDay == true) {
break;
}
flag++;
nextDay = nextDay.plusDays(1L);
if (flag == 365) {
nextDay = null;
break;
}
}
return Optional.ofNullable(nextDay);
}
@Override
public List<LocalDate> queryBetween(LocalDate from, LocalDate to) {
int duringDays = to.getDayOfYear() - from.getDayOfYear();
LinkedList<LocalDate> localDates = new LinkedList<>();
for (int i = 0; i <= duringDays; i++) {
LocalDate date = from.plusDays(Long.parseLong(String.valueOf(i)));
if (this.isTradingDay(date)) {
localDates.add(date);
}
}
return localDates;
}
@Override
public Optional<LocalDate> queryFirstTradingDayOfMonth(LocalDate date) {
int dayOfMonth = date.getDayOfMonth();
LocalDate day = date.minusDays(dayOfMonth);
return this.queryNextTradingDay(day);
}
}
测试用例类
public class TradingDayServiceTest {
private static TradingDayService tradingDayService = new TradingDayServiceImpl();
public static void main(String[] args) {
long start = System.currentTimeMillis();
//testTradingDay(); 耗时0.4s--0.5s
//testQueryNextTradingDay(); 耗时 0.36s左右
//testQueryFirstTradingDayOfMonth(); 耗时:0.2s--0.5s
testQueryBetween(); //0.2s--0.3s
System.out.println(System.currentTimeMillis() - start);
}
public static void testTradingDay(){
LocalDate date = LocalDate.parse("2020-02-04");
System.out.println(tradingDayService.isTradingDay(date));
}
public static void testQueryNextTradingDay() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDate = LocalDate.parse("2020-12-04");
Optional<LocalDate> tradingDate = tradingDayService.queryNextTradingDay(localDate);
tradingDate.ifPresent(u->{
System.out.println(u.format(formatter));;
});
}
public static void testQueryFirstTradingDayOfMonth(){
LocalDate date = LocalDate.parse("2020-12-24");
Optional<LocalDate> localDate = tradingDayService.queryFirstTradingDayOfMonth(date);
localDate.ifPresent(u->{
System.out.println(u.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
});
}
public static void testQueryBetween(){
LocalDate from = LocalDate.parse("2021-01-02");
LocalDate to = LocalDate.parse("2022-02-13");
List<LocalDate> localDates = tradingDayService.queryBetween(from, to);
localDates.forEach(u->{
System.out.println(u.toString());
});
}
}
以上就是我的实现方式。写的不好,大家可以提出建议,加依修改。我只是以个人的想法实现的代码,肯定有很多不足之处,欢迎大家评论。