0

我有一个看起来或多或少像这样的 HashMap:

private HashMap<String, String> fu = new HashMap<String, String>();

fu.put("16:04:00.476", "A");
fu.put("16:09:58.228", "B");
fu.put("16:17:58.227", "C");
fu.put("16:22:42.478", "D");
fu.put("16:27:23.728", "E");
fu.put("16:38:34.977", "F");
fu.put("16:46:46.227", "G");

现在我有了另一个时间戳,叫做 bar,我想找到合适的字母:

private String findLetter(String timestamp) {
   return "";
}

HashMap 中的时间戳可以被认为是开始时间。这意味着,A 从 16:04:00.476 开始,一直持续到 B 开始。B 一直持续到 C 开始,依此类推。现在,这个方法应该返回作为参数传递的时间戳所在的字母。

我做的第一件事是将时间戳转换为日期对象,以使用 Date#after 方法查看它是否在某个开始时间之后,但是如何确保它也在下一个开始时间之前?

4

5 回答 5

6

HashMap 没有顺序,所以首先你应该使用 TreeMap,例如。并查看下一个条目以检查它是否在您当前的时间戳之后

于 2013-06-06T19:40:37.853 回答
0

如果您的密钥格式没有改变,您可以简单地执行以下操作:

private NavigableMap<String, String> fu = new TreeMap<>();

进而

private String findLetter(String timestamp) {
    return map.get(map.lowerKey(timestamp));
}

如果你以后打算改变格式,你可以做以下(但必须调整时间格式)

private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS");

private NavigableMap<String, String> fu = new TreeMap<>(new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        try {
            long t1 = DATE_FORMAT.parse(o1).getTime();
            long t2 = DATE_FORMAT.parse(o2).getTime();
            return Long.compare(t1, t2);
        } catch (ParseException e) {
            throw new IllegalArgumentException(e);
        }
    }
});

然后你可以简单地做

private String findLetter(String timestamp) {
       return map.get(map.lowerKey(timestamp));
}
于 2013-06-06T19:48:22.447 回答
0

TreeMap正如建议的那样,这是基于 的简单解决方案。它假定您显示的所有时间点都在同一天。

class Sample {

    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");

    private static final String DEFAULT_DAY_PREFIX = "1980-05-15 ";

    public static void main(String[] args) throws ParseException {

        TreeMap<Long, String> orderedDates = new TreeMap<Long, String>();

        orderedDates.put(parseToDate("16:04:00.476"), "A");
        orderedDates.put(parseToDate("16:09:58.228"), "B");
        orderedDates.put(parseToDate("16:17:58.227"), "C");

        System.out.println(orderedDates.floorEntry(parseToDate("16:04:00.500")).getValue());
        System.out.println(orderedDates.floorEntry(parseToDate("16:09:58.100")).getValue());
        System.out.println(orderedDates.floorEntry(parseToDate("16:09:58.300")).getValue());
        System.out.println(orderedDates.floorEntry(parseToDate("16:17:58.300")).getValue());
    }

    private static long parseToDate(String dayPoint) throws ParseException {
        return SDF.parse(DEFAULT_DAY_PREFIX + dayPoint).getTime();
    }
}
于 2013-06-06T19:48:34.857 回答
0

如果您已经将 s 解析StringDates,那么您可以使用唯一不推荐使用的方法之一,该方法getTime()将返回long表示毫秒的 a。

然后你可以比较这个值,假设 0 是Epoch,并且在我写这个答案时它是1370548040476.

于 2013-06-06T19:50:03.247 回答
0

我以更方便的方式修改了您的源代码,以便向您展示如何正确执行此操作。我将把它留给你做一个练习,让它按照你想要的方式工作,但 IMO 很容易看出如何去做。这使用了 JodaTime 库。

package com.sandbox;

import org.joda.time.DateTime;
import org.joda.time.Interval;

import java.util.ArrayList;
import java.util.List;

public class Sandbox {

    public static void main(String[] args) {
        List<DateTime> dateTimes = new ArrayList<DateTime>();
        dateTimes.add(new DateTime(100000));
        dateTimes.add(new DateTime(105000));
        dateTimes.add(new DateTime(110000));
        dateTimes.add(new DateTime(115000));
        dateTimes.add(new DateTime(120000));

        List<Interval> intervals = new ArrayList<Interval>();

        for (int i = 0; i < dateTimes.size() - 1; i++) {
            DateTime start = dateTimes.get(i);
            DateTime end = dateTimes.get(i + 1);
            intervals.add(new Interval(start, end));
        }

        assert 0 == findIndex(100000L, intervals);
        assert 0 == findIndex(100001L, intervals);
        assert 3 == findIndex(115000L, intervals);
        assert 3 == findIndex(115001L, intervals);
    }

    private static Integer findIndex(Long timestamp, List<Interval> intervals) {
        DateTime dateTime = new DateTime(timestamp);

        for (int i = 0; i < intervals.size(); i++) {
            Interval interval = intervals.get(i);
            if (interval.contains(dateTime)) {
                return i;
            }
        }
        return -1;
    }


}

当您认为@Thierry 的解决方案有效时,这比所需的工作量要多得多。但是如果您的需求发生变化,这段代码可能会更灵活地适应这些变化。不过,如果您认为您的要求不会改变,我会先使用他的建议。

于 2013-06-06T19:51:19.327 回答