Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Старайтесь как можно реже использовать оператор instanceOf. Это один из самых медленных java операторов
s = s + fileds[i]s = new StringBuilder(s).append(fields[i]).toString();String[] fields = new String[] {"a","b","c","d","e","f","g"};
String s = "";
for (int i = 0; i < fields.length; i++) {
s = s + fields[i];
doSomeThing(s);
}
int a = 12;
String s = a + "";
вместо String s = String.valueOf(12);$a = "2";
$a = $a + 0; // преобразовуем в число
var a = '7';
var b = a - 0;
А в PHP достаточно такого: $a = (int|bool|array|string|object)$a;
ну кому, кому блин может придти в голову, намеренно преобразовать число в строку через конкатенацию числа и строкиКажется, что в голову прийти не может, пока не начинаешь читать чужой код и общаться на форумах) Такое (и хуже) сплошь и рядом. Ниже каменты с плюсами, где на это говорится в духе «а что такого».
for(i=0;i<array.length;i++) item=array[i];for(item:array)private static void two(String[] fields) {
for (String s : fields) {
System.out.println(s);
fields = null;
}
System.out.println(fields);
}
private static void one(String[] fields) {
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
fields = null;
}
System.out.println(fields);
}
private void one(java.lang.String[]);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: aload_1
4: arraylength
5: if_icmpge 23
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_1
12: iload_2
13: aaload
14: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: iinc 2, 1
20: goto 2
23: return
private void two(java.lang.String[]);
Code:
0: aload_1
1: astore_2
2: aload_2
3: arraylength
4: istore_3
5: iconst_0
6: istore 4
8: iload 4
10: iload_3
11: if_icmpge 36
14: aload_2
15: iload 4
17: aaload
18: astore 5
20: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
23: aload 5
25: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: aconst_null
29: astore_1
30: iinc 4, 1
33: goto 8
36: return
}
mov cx, 10
label:
...
loop label
for(int i=0, size = array.length; i < size; i++) item=array[i];
* This source code was highlighted with Source Code Highlighter.for(int i=0;i<array.length;i++)for(int i=0, size = array.length;i<size;i++)вместо
for(i=0;i<array.length;i++) item=array[i];
используйте
for(item:array)
String[] fields = new String[] {"a","b","c","d","e","f","g"};
String s = "";
for (int i = 0; i < fields.length; i++) {
s = s + fields[i];
}
return s;иString[] fields = new String[] {"a","b","c","d","e","f","g"};
String s = "";
for (int i = 0; i < fields.length; i++) {
s += fields[i];
}
return s;но к производительности это имхо не имеет практически никакого отношения.
так как в StringBuilder нету синхронизированных методов в отличие от StringBuffer и следовательно производительность будет выше, хоть и не значительно.Это фактически бесполезное опасение, при однопоточном доступе лишняя синхронизация отлично оптимизируется компилятором по крайней мере до lightweight locking, а то и до пропуска блокировки (в данных примерах скорее всего). В любом случае это точно не то, что программисту стоит первым делом оптимизировать.
можно увеличить кеш для Integer через системное свойство «java.lang.Integer.IntegerCache.high», а так же через параметр виртуальной машины -XX:AutoBoxCacheMax=Тут нужно сказать, что речь только о 7 версии, ибо до сих пор это было захардкожено внутри java.lang.Integer. Думаю, для многих это сюрприз :)
//медленно
Integer i = new Integer(100);
...
//быстро
Integer i = Integer.valueOf(100);Что думает читатель? «Ага, valueOf быстрее, чем new». Верно думает читатель? Нет. Оно быстрее в общем случае только если в скобках определённые числа. Если мы напишем так://медленно
Integer i = new Integer(200);
...
//быстро
Integer i = Integer.valueOf(200);, то это уже, очевидно, неправда — ведь всё противоположно, не так ли? Первый отрезок быстрее второго. Да, быстрее на три с половиной тика, но раз уж взялись экономить на спичках — договаривайте до конца :)то это уже, очевидно, неправда
речь только о 7 версии
getAndRemoveCacheProperties>null vs empty
>
> Всегда старайтесь в методах вашей бизнес логики возвращать пустые коллекции вместо null значений, это избавляет от лишних null-проверок и делает код чище.
{
...
some_list:[],
...
}{
...
some_list:null,
...
}private static String x() {
return "...";
}
private static String y() {
return new String("...");
}
private static java.lang.String x();
Code:
0: ldc #2; //String ...
2: areturn
private static java.lang.String y();
Code:
0: new #3; //class java/lang/String
3: dup
4: ldc #2; //String ...
6: invokespecial #4; //Method java/lang/String."<init>":(Ljava/lang/String;)V
9: areturn
}
Скажем, я лично не уверен, что new String("...") и «ююю» вообще компилируется в разные вещи.
Скажем «Преобразование чисел» предложение оно вообще непонятно как может быть скомпилировано иначе чем в valueOf.
Про отличия стринг билдера и буфера, это вообще очень странный совет, синхронизация дальше BIAS не надуется и на производительности скажется не более, чем сверка threadId с монитором. Сомневаюсь, что это сильный аргумент. Хотя, конечно билдер использовать более правильно, но на перформанс кивать тут довольно глупо, если это не мегаострое место в программе.
Боятся instanceof тоже не стоит, где-то была работа где изучались разные виды multiple dispatch...
Тормознутость рефлекшена, кстати опять же сильно преувеличена, при умелом подходе оно бегает довольно шустро.
Синхронизация дает значительный (относительно) удар даже при однопоточном выполнении.Это не совсем так, выше я написал отчего. Не даёт синхронизация никакого удара при однопоточном выполнении. По крайней мере если конкретно говорить о HotSpot. А мы, судя по статье и комментариям автора говорим именно о ней. Если не говорить конкретно о какой-то машине, то практически ни один из данных советов не имеет какого-то смысла.
/**
* Returns a <code>Long</code> object holding the value
* of the specified <code>String</code>. The argument is
* interpreted as representing a signed decimal <code>long</code>,
* exactly as if the argument were given to the {@link
* #parseLong(java.lang.String)} method. The result is a
* <code>Long</code> object that represents the integer value
* specified by the string.
* <p>
* In other words, this method returns a <code>Long</code> object
* equal to the value of:
*
* <blockquote><pre>
* new Long(Long.parseLong(s))
* </pre></blockquote>
*
* @param s the string to be parsed.
* @return a <code>Long</code> object holding the value
* represented by the string argument.
* @exception NumberFormatException If the string cannot be parsed
* as a <code>long</code>.
*/
public static Long valueOf(String s) throws NumberFormatException
{
return new Long(parseLong(s, 10));
}
/**
* Returns a <tt>Long</tt> instance representing the specified
* <tt>long</tt> value.
* If a new <tt>Long</tt> instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Long(long)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param l a long value.
* @return a <tt>Long</tt> instance representing <tt>l</tt>.
* @since 1.5
*/
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
public class NewMain {
static final long iterations = 10000L * 1000000L;
public static void main(String[] args) {
Runnable doNew = new Runnable() {
public void run() {
int s = 0;
for (long i = 0; i < iterations; ++i) {
Integer v = new Integer(100);
s += v;
}
}
};
Runnable doValue = new Runnable() {
public void run() {
int s = 0;
for (long i = 0; i < iterations; ++i) {
Integer v = Integer.valueOf(100);
s += v;
}
}
};
measure("valueOf", doValue);
measure("new", doNew);
measure("valueOf", doValue);
measure("new", doNew);
}
private static void measure(String msg, Runnable r) {
long start = System.currentTimeMillis();
r.run();
long ela = System.currentTimeMillis() - start;
System.out.println(msg + " elapsed " + ela + ", rps " + (iterations / ela) * 1000);
}
}
measure("valueOf", doValue);
Thread.yield();
measure("new", doNew);
Thread.yield();
measure("valueOf", doValue);
Thread.yield();
measure("new", doNew);valueOf elapsed 19938, rps 501554000Это показывает только, что есть вероятная (!) разница порядка секунды на 10 миллиардах (!) итераций.
new elapsed 18235, rps 548395000
valueOf elapsed 19242, rps 519696000
new elapsed 20556, rps 486475000
''true''.equals(str)//плохо
interface A {
public static final String A = "a";
}
//аналогично плохо
interface A {
String A = "a";
}
Маленькие хитрости Java