- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
/**
* Parses inlined match flags and set them appropriately.
*/
private void addFlag() {
int ch = peek();
for (;;) {
switch (ch) {
case 'i':
flags |= CASE_INSENSITIVE;
break;
case 'm':
flags |= MULTILINE;
break;
case 's':
flags |= DOTALL;
break;
case 'd':
flags |= UNIX_LINES;
break;
case 'u':
flags |= UNICODE_CASE;
break;
case 'c':
flags |= CANON_EQ;
break;
case 'x':
flags |= COMMENTS;
break;
case '-': // subFlag then fall through
ch = next();
subFlag();
default:
return;
}
ch = next();
}
}
/**
* Parses the second part of inlined match flags and turns off
* flags appropriately.
*/
private void subFlag() {
int ch = peek();
for (;;) {
switch (ch) {
case 'i':
flags &= ~CASE_INSENSITIVE;
break;
case 'm':
flags &= ~MULTILINE;
break;
case 's':
flags &= ~DOTALL;
break;
case 'd':
flags &= ~UNIX_LINES;
break;
case 'u':
flags &= ~UNICODE_CASE;
break;
case 'c':
flags &= ~CANON_EQ;
break;
case 'x':
flags &= ~COMMENTS;
break;
default:
return;
}
ch = next();
}
}
если и говно - то не очевидное.
вот именно из-за таких вот [spoiler]говно[/spoiler]кодеров в классе over95K строк
тут есть гораздо более очевидное говно
http://govnokod.ru/3566
а васик (или дельфи) минусовать, это все равно что над ущербными детишками глумится...
мне насрать - твое право, только вот спецом по жабе не надо быть чтоб понять где тут говно ибо оно везде
tips:
a) case не нужен - юзай мап
б) две функции сливай в одну dsflag(boolean add) и инвертируй в зав add
private void addFlag() {dsflag(true);}
private void subFlag() {dsflag(false);}
алсо как заметил Lure Of Chaos for (;;) - и неочевидный выход из цикла, но это уже тонкости, по сранению с вышенаписанным
я понимаю если бы в коде был реальный и неочевидный баг...
как минима - свести 2 функции в 1.
потом есть for
почему бы нам не написать, что-то вроде
for (int ch = peek();<условие мапа>;ch = next();)
>>map будет медленее чем switch/case.
да неужели? есть разные мапы - TreeMap например - поиск по дереву быстрее перебора инфа 100%.
а еще есть массивы, в которых вообще нет перебора короче если подумать головой а не руками - можно
а) существенно сократить код
б) убрать дублирование
в) ускорить его
но, думаю это слишком сложно, проще глумится над ущербными детишками.
или просто переведет case в кучу ифов? ))
на switch/case есть разные оптимизации. самая крутая которую я видел это был двоичный поиск полностью заинлайненый в коде. т.е. как бы мап без мапа, сгенерированый самим компилятором.
да-да-да знаем мы эти оптимизации, на словах - чудеса, а на деле в самых простых моментах говно.
для тех кто еще сомневается в говености сего, нашел нормальную некитайскую Apache имплементацию класса от (как это не странно) нашего соотечественника @author Nikolay A. Kuznetsov
http://www.docjar.com/html/api/java/util/regex/Pattern.java.html
1400 строк заместо 5600!!! и это при том что коментариев там дохера и они никуда не делись over 4 раза сокращение объема
так вот там этой логики вообще нет, что кагбе намекает...
это про то, как компилируются свичи. Если вкратце, то в зависимости от того, какие у свича есть case-ы, они компилируются либо с использованием массива(tableswitch), с доступом за O(1), либо в некоторую струкруту, отсортированную по ключу(lookupswitch). Явно в стандарте не говорится, какой алгоритм использовать, но производительность явно не хуже O(logN), где N -- число case-ов.
Дело, правда, в том, что различия в скорости могут оказаться очень мизерными, вплоть до наносекунд, которыми вполне можно принебречь.
Where the cases of the switch are sparse, the table representation of the tableswitch instruction becomes inefficient in terms of space. The lookupswitch instruction may be used instead. The lookupswitch instruction pairs int keys (the values of the case labels) with target offsets in a table. When a lookupswitch instruction is executed, the value of the expression of the switch is compared against the keys in the table. If one of the keys matches the value of the expression, execution continues at the associated target offset. If no key matches, execution continues at the default target.
то есть приведенный пример будет компилится в lookupswitch и тут главное
the expression of the switch is compared against the keys in the table
то есть некий поиск о чем мы и говорим
>tableswitch и lookupswitch работают куда быстрее, чем любая реализация, которую может написать человек на java
предложенный мною вариант - вообще работает без поиска
http://govnokod.ru/4054#comment44492
>т.к. каждый из них -- одна-единственная инструкция для JVM.
но так как там lookup в table - то это компилится в целую тучу ассм-инструкций
вот это как раз-таки не факт. В принципе, case-ы не особо разбросаны, так что может закомпилиться и в tableswitch.
впрочем, если скомпилится в лукап -- то, скорее всего, ручная реализация на массивах (что есть этакий аналог tableswitch-a) может оказаться быстрее.
но я всё-таки думаю, что адекватные компиляторы поймут, что в этом случае tableswitch можно юзать спокойно.
ЗЫ: я не знаю, с какой скоростью работают мэпы.
но всё же думаю, что вариант со switch-case будет шустрее, а в регулярках важнее всего скорость, как ни крути. Юзать Map из 7 элементов = из пушки по воробьям.
По поводу дублирования функций согласен.
private static final char[] FLAG_SYMBOLS = {
'i', 'm', 's', 'd', 'u', 'c', 'x'
};
private static final int[] FLAG_BITS = {
CASE_INSENSITIVE, MULTILINE, DOTALL, UNIX_LINES, UNICODE_CASE, CANON_EQ, COMMENTS
};
private void addFlag() {
boolean valid = true;
for(char ch = peek(); valid; ch = next()) {
valid = addFlag(ch, false);
}
}
private boolean addFlag(char ch, boolean resetFlag) {
if (ch == '-') {
addFlag(next(), true);
}
int index = Arrays.binarySearch(FLAG_SYMBOLS, ch);
if (index != -1) {
int flagBit = FLAG_BITS[index];
if (resetFlag) {
flags &= ~flagBit;
} else {
flags |= flagBit;
}
return true;
}
return false;
}
правда, читать это немного сложнее, чем китайский вариант, плюс, добавляется зависимость от класса Arrays.
Ыыы)) ну вы блин даете.
итак мой вариант (заточенный на скорость)
1.сначала проверяем является ли символ маленькой буквой - нет на выход (отдельно прописываем if (ch == '-') {)
2.создаем static final char[] SYMB 26 элементов для маленьких букв - всю ту хероту заносим в массив, все окромя 'i', 'm', 's', 'd', 'u', 'c', 'x' забиваем неким EMPTY.
условие выхода из цикла SYMB[ch-'a']==EMPTY - все никаких бинарных поисков и пр.
+ массив - самая быстрая реализация, быстрее огромного свитча. ИНФА 100%
>Если для получения флагов будут использоваться цифры, то 26-символьного int[] массива уже будет недостаточно.
это был пример заточеннный на скорость
+1
В комментах срать лучше словами.
Кодом срут только в самом верху.
Константа у бинпоиска больше, если массив маленький, то линейный поиск будет быстрее. Как, например, в этом случае.
да и если не так много элементов - switch еще и наглядней