笔试题——用java实现股票交易日的判断

今天记录一道笔试题

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());
        });


    }
}

以上就是我的实现方式。写的不好,大家可以提出建议,加依修改。我只是以个人的想法实现的代码,肯定有很多不足之处,欢迎大家评论。


版权声明:本文为China_TomCat原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。