Java - Как из строки времени (hh::mm::ss.SSS) вытащить минуты? - Stack Overflow на русском
Опубликовано: 05.09.2018
Зачем использовать регулярное выражение для такой примитивной задачи?
String s1 = "10:11:23.555"; String[] tokens = s1.split(":"); String minutes = tokens[1];
UPDATE: Раз автор вопроса озабочен производительностью, а @MedvedevDev интересуется устройством String.split() , вопрос переходит в статус более-менее интересных, и я не могу не развернуть ответ.
Прежде всего надо заметить, что реализация методов стандартной библиотеки может отличаться в разных реализациях JVM или даже разных версиях одной и той же JVM. Причём метод может пробрасывать вызов в Сишный код , использующий SIMD-инструкции процессора , как это делает String.indexOf() например.
Урок по Java 48: Даты, календари и время.
В Java 8 на HotSpot метод split, как правильно заметил @Nick, использует регулярные выражения только для аргумента из нескольких символов или содержащего мета-символы. Иначе положения разделителя перебираются в цикле с помощью уже упомянутого мной indexOf:
int off = 0; int next = 0; while ((next = indexOf(ch, off)) != -1) { list.add(substring(off, next)); off = next + 1; }Посмотреть можно здесь .
17.22 New Date Time Api in Java 8
Грешно было бы не проверить разницу в скорости между таким подходом и использованием регулярного выражения. Я набросал для этого тест JMH :
public class SplitBenchmark { @State(Scope.Benchmark) public static class BenchmarkState { public List<String> strings; public Pattern groupPattern; public Pattern splitPattern; @Setup(Level.Trial) public void setup() { groupPattern = Pattern.compile(":(\\d+):"); splitPattern = Pattern.compile(":"); Random random = new Random(); strings = IntStream.rangeClosed(0, 100_000) .mapToObj(x -> random.ints(0, 99) .mapToObj(i -> String.format("%02d", i)) .limit(3) .collect(Collectors.joining(":"))) .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)); } } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void regexGroupMatching(BenchmarkState state, Blackhole blackhole) { for (int i = 0; i < state.strings.size(); i++) { String s = state.strings.get(i); Matcher m = state.groupPattern.matcher(s); if (m.find()) { String minutes = m.group(1); blackhole.consume(minutes); } } } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void regexPatternSplit(BenchmarkState state, Blackhole blackhole) { for (int i = 0; i < state.strings.size(); i++) { String s = state.strings.get(i); String[] tokens = state.splitPattern.split(s); String minutes = tokens[1]; blackhole.consume(minutes); } } @Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public void stringSplit(BenchmarkState state, Blackhole blackhole) { for (int i = 0; i < state.strings.size(); i++) { String s = state.strings.get(i); String[] tokens = s.split(":"); String minutes = tokens[1]; blackhole.consume(minutes); } } }Результат:
Benchmark Mode Cnt Score Error Units SplitBenchmark.regexGroupMatching avgt 25 10,382 ? 0,120 ms/op SplitBenchmark.regexPatternSplit avgt 25 17,235 ? 0,240 ms/op SplitBenchmark.stringSplit avgt 25 7,906 ? 0,069 ms/opКак можно видеть, String.split() самый быстрый, а Pattern.split() существенно медленнее даже извлечения групп, чем я сам удивлён.
Сегодня | Завтра | ||
USD | 32.62 | 32.50 | |
EUR | 39.90 | 39.92 |
Обменник | Переходов |
Wmchanger | 6 |
E-Market | 5 |
WMtoCash.com | 4 |
Str-Money | 3 |
Hot-Change | 3 |
Вы можете получить WMR-бонус в размере 0,01-0,10 WMR на свой кошелек 1 раз в сутки | |
Кошелек
|
|
Код
|
|
Обмен Webmoney |