下面的代码是我用来比较代码优化前后的性能
1. import
2. import
3. import
4. import
5. import
6. import
7. import
8.
9. public class
10.
11. public static void
12.
13. /*
14. * 避免在循环条件中使用复杂表达式
15. * @author yifangyou
16. * @since 2011-08-16 09:35:00
17. *
18. */
19. // test0();
20. /*
21. * 如果只是查找单个字符的话,用charAt()代替startsWith()
22. * @author yifangyou
23. * @since 2011-08-16 09:35:00
24. */
25. // test1();
26.
27.
28. /*
29. * 能够使用移位的乘除,最好用移位
30. * @author yifangyou
31. * @since 2011-08-16 09:35:00
32. */
33. // test2();
34.
35. /*
36. * 只有一个字符的字符串拼接,用''代替""
37. * @author yifangyou
38. * @since 2011-08-16 09:35:00
39. */
40. // test3();
41.
42. /**
43. * try catch最好不要放在循环里
44. * @author yifangyou
45. * @since 2011-08-16 09:35:00
46. */
47. // test4();
48.
49. /**
50. * switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害
51. * @author yifangyou
52. * @since 2011-08-16 09:35:00
53. */
54. // test5();
55.
56. /*
57. * 对于常量字符串,用'String' 代替 'StringBuffer' ,节省空间,节省时间
58. * @author yifangyou
59. * @since 2011-08-16 09:35:00
60. */
61. // test6();
62. /*
63. * 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
64. * 字符串的分析在很多应用中都是常见的。使用indexOf
65. * ()和substring()来分析字符串容易导致StringIndexOutOfBoundsException。
66. * 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
67. * @author yifangyou
68. * @since 2011-08-16 09:35:00
69. */
70. // test7();
71.
72. /*
73. * 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
74. * @author yifangyou
75. * @since 2011-08-16 09:35:00
76. */
77. // test8();
78. /*
79. * 确定 StringBuffer的容量
80. * StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小
81. * ,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
82. * StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
83. * @author yifangyou
84. * @since 2011-08-16 09:35:00
85. */
86. // test9();
87. /*
88. * 尽可能的使用栈变量
89. *
90. * 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
91. * local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
92. * @author yifangyou
93. * @since 2011-08-16 09:35:00
94. */
95. // test10();
96. /**
97. * 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
98. * @author yifangyou
99. * @since 2011-08-16 09:35:00
100. */
101.
102. // copyArray();
103. /*
104. * 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
105. * @author yifangyou
106. * @since 2011-08-16 09:35:00
107. */
108. // copyArrayList();
109. /*
110. * 复制Map最好用逐个复制最快,putAll最简单
111. * @author yifangyou
112. * @since 2011-08-16 09:35:00
113. */
114. copyMap();
115.
116.
117. }
118.
119. int localN = 0;
120. static int staticN = 0;
121.
122. /*
123. * 避免在循环条件中使用复杂表达式
124. * @author yifangyou
125. * @since 2011-08-16 09:35:00
126. */
127. public static void
128. new
129.
130. for (int i = 0; i < 10000000; i++) {
131. a.add(i);
132. }
133.
134. long
135. // 循环条件中使用复杂表达式
136. new
137. for (int i = 0; i < a.size(); i++) {
138. int
139. }
140. new
141.
142. // 循环条件中不使用复杂表达式
143. new
144. for (int i = 0, maxlen = a.size(); i < maxlen; i++) {
145. int
146. }
147. new
148. }
149.
150. /*
151. * 如果只是查找单个字符的话,用charAt()代替startsWith()
152. * @author yifangyou
153. * @since 2011-08-16 09:35:00
154. */
155. public static void
156. "sdfsdfsdfsdfdssssssssssssssssssssssssssssdfffffffffffffffa";
157. long
158. // startsWith
159. new
160. for (int i = 0; i < 10000000; i++) {
161. if (s.startsWith("a")) {
162.
163. }
164. }
165. new
166. // charAt
167. new
168. for (int i = 0; i < 10000000; i++) {
169. if (s.charAt(0) == 'a') {
170.
171. }
172. }
173. new
174.
175. // charAt
176. new
177. for (int i = 0; i < 10000000; i++) {
178. if ("ab".equals("abcdssdds".substring(0, 2))) {
179.
180. }
181. }
182. new
183.
184. }
185.
186. /*
187. * 能够使用移位的乘除,最好用移位
188. * @author yifangyou
189. * @since 2011-08-16 09:35:00
190. */
191. public static void
192. long
193. int
194. //
195. new
196.
197. for (int i = 0; i < 10000000; i++) {
198. 333333333 / 8;
199. }
200. new
201. // charAt
202. new
203. for (int i = 0; i < 10000000; i++) {
204. 333333333 >> 3;
205. }
206. new
207. }
208.
209. /*
210. * 只有一个字符的字符串拼接,用''代替""
211. * @author yifangyou
212. * @since 2011-08-16 09:35:00
213. */
214. public static void
215. long
216.
217. new
218. "123";
219. for (int i = 0; i < 10000000; i++) {
220. "d";
221. }
222. new
223. // charAt
224. new
225. for (int i = 0; i < 10000000; i++) {
226. 'd';
227. }
228. new
229. }
230.
231. /**
232. * try catch最好不要放在循环里
233. * @author yifangyou
234. * @since 2011-08-16 09:35:00
235. */
236. public static void
237. long
238. new
239. for (int i = 0; i < 10000000; i++) {
240. try
241. int a = Integer.parseInt("1");
242. catch
243.
244. }
245. }
246. new
247.
248. new
249. try
250. for (int i = 0; i < 10000000; i++) {
251. int a = Integer.parseInt("1");
252. }
253. catch
254.
255. }
256.
257. new
258.
259. }
260.
261. /**
262. * switch的实现 map比较稳定,if最慢,switch在数量少于10个时最快,随着数量增加下降厉害,在switch最好把出现次数最多的判断放在最前面
263. * @author yifangyou
264. * @since 2011-08-16 09:35:00
265. */
266. public static void
267. new
268. {
269. int i = 0;
270. this.put("a", i++);
271. this.put("b", i++);
272. this.put("c", i++);
273. this.put("d", i++);
274. this.put("e", i++);
275. }
276. };
277. "e";
278. int b = 0;
279. long
280. new
281. for (int i = 0; i < 10000000; i++) {
282. if ("a".equals(a)) {
283. 0;
284. else if ("b".equals(a)) {
285. 1;
286. else if ("c".equals(a)) {
287. 2;
288. else if ("d".equals(a)) {
289. 3;
290. else if ("e".equals(a)) {
291. 4;
292. }
293. }
294. new
295.
296. new
297. for (int i = 0; i < 10000000; i++) {
298. b = types.get(a);
299. }
300. new
301. int c = 14;//改为0的话则最快
302. new
303. for (int i = 0; i < 10000000; i++) {
304. switch
305. case 0:
306. break;
307. case 1:
308. break;
309. case 2:
310. break;
311. case 3:
312. break;
313. case 4:
314. break;
315. case 5:
316. break;
317. case 6:
318. break;
319. case 7:
320. break;
321. case 8:
322. break;
323. case 9:
324. break;
325. case 10:
326. break;
327. case 11:
328. break;
329. case 12:
330. break;
331. case 13:
332. break;
333. case 14:
334. break;
335. default:
336. break;
337. }
338. }
339.
340. new
341. }
342.
343. /*
344. * 对于常量字符串,用'String' 代替 'StringBuffer' ,节省空间,节省一半时间
345. * @author yifangyou
346. * @since 2011-08-16 09:35:00
347. */
348. public static void
349. new StringBuffer("Hello");
350. int maxlen=1000000;
351. long
352. new
353. for (int i = 0; i < maxlen; i++) {
354. new String("Hello ") + "World!";
355. }
356. new
357.
358. new
359. for (int i = 0; i < maxlen; i++) {
360. new StringBuffer("Hello ").append("World!");
361. }
362. new
363. }
364.
365. /*
366. * 用'StringTokenizer' 代替 'indexOf()' 和'substring()'
367. * 字符串的分析在很多应用中都是常见的。使用indexOf
368. * ()和substring()来分析字符串容易导致StringIndexOutOfBoundsException。
369. * 而使用StringTokenizer类来分析字符串则会容易一些,效率也会低一些。
370. * @author yifangyou
371. * @since 2011-08-16 09:35:00
372. */
373. public static void
374. "www.a.com.";
375. long
376. new
377.
378. for (int i = 0; i < 100000; i++) {
379. int index = 0;
380. while ((index = domain.indexOf(".", index + 1)) != -1) {
381. 1, domain.length());
382. // System.out.println(domain.substring(index+1,
383. // domain.length()));
384. }
385. }
386. new
387. new
388. for (int i = 0; i < 100000; i++) {
389. new StringTokenizer(domain, ".");
390. while
391. st.nextToken();
392. // System.out.println(st.nextToken());
393. }
394. }
395. new
396. }
397.
398. /*
399. * 不要在循环体中实例化变量 在循环体中实例化临时变量将会增加内存消耗
400. * @author yifangyou
401. * @since 2011-08-16 09:35:00
402. */
403. public static void
404. new
405. int maxlen = 10000000;
406. for (int i = 0; i < maxlen; i++) {
407. a.add(i);
408. }
409. long
410. new
411. for (int i = 0; i < maxlen; i++) {
412. new
413. o = a.get(i);
414. }
415. new
416. new
417. new
418. for (int i = 0; i < maxlen; i++) {
419. o = a.get(i);
420. }
421. new
422. }
423.
424. /*
425. * 确定 StringBuffer的容量
426. * StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存
427. * ,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建
428. * StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
429. * @author yifangyou
430. * @since 2011-08-16 09:35:00
431. */
432. public static void
433. int maxlen = 1000000;
434. long
435. new
436. for (int i = 0; i < maxlen; i++) {
437. new StringBuffer(); // violation
438. "hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
439. }
440. new
441. new
442. for (int i = 0; i < maxlen; i++) {
443. new StringBuffer(128); // violation
444. "hellosdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
445. }
446. new
447. }
448.
449. /*
450. * 尽可能的使用栈变量 如果一个变量需要经常访问,那么你就需要考虑这个变量的作用域了。static?
451. * local?还是实例变量?访问静态变量和实例变量将会比访问局部变量多耗费2-3个时钟周期。
452. * @author yifangyou
453. * @since 2011-08-16 09:35:00
454. */
455. public static void
456. int maxlen = 100000000;
457. long
458. int n = 0;
459. new
460. // 局部变量
461. new
462. for (int i = 0; i < maxlen; i++) {
463. n = i;
464. }
465. new
466. // 类变量
467. new
468. for (int i = 0; i < maxlen; i++) {
469. test.localN = i;
470. }
471. new
472.
473. // 静态变量
474. new
475. for (int i = 0; i < maxlen; i++) {
476. Test.staticN = i;
477. }
478. new
479. }
480. //
481. // /*1.尽量使用final修饰符。
482. //带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如java.lang.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。
483. // */
484. // public static void test11() {
485. // int maxlen = 10000000;
486. // long startTime;
487. // int n = 0;
488. //
489. // // 普通类
490. // startTime = new Date().getTime();
491. // A a = new A();
492. // for (int i = 0; i < maxlen; i++) {
493. // a.inc();
494. // }
495. // System.out.println(new Date().getTime() - startTime);
496. //
497. // // final类
498. // startTime = new Date().getTime();
499. // FinalA finalA = new FinalA();
500. // for (int i = 0; i < maxlen; i++) {
501. // finalA.inc();
502. // }
503. // System.out.println(new Date().getTime() - startTime);
504. // }
505.
506. /**
507. * 复制数组最好用System.arraycopy 逐个复制,最慢;批量复制,最快
508. * @author yifangyou
509. * @since 2011-08-16 09:35:00
510. */
511. static void
512. int[] array1 = new int[10000000];
513. int[] array2 = new int[10000000];
514. for (int i = 0, maxlen = array1.length; i < maxlen; i++) {
515. array1[i] = i;
516. }
517.
518. long
519. // 逐个复制,最慢
520. new
521.
522. for (int i = 0, maxlen = array2.length; i < maxlen; i++) {
523. // Violation
524. }
525. new
526.
527. // 批量复制,最快
528. new
529. 0, array2, 0, 10000);
530. new
531.
532. }
533.
534. /*
535. * 复制ArrayList数组最好用addAll addAll,最快;clone,次之,逐个最慢
536. * @author yifangyou
537. * @since 2011-08-16 09:35:00
538. */
539. static void
540. int maxlen = 1000000;
541. new
542. new
543. new
544. ArrayList<Integer> array4;
545. for (int i = 0; i < maxlen; i++) {
546. array1.add(i);
547. }
548.
549. long
550. // 逐个复制,最慢
551. new
552.
553. for (int i = 0; i < maxlen; i++) {
554. // Violation
555. }
556. new
557.
558. // 批量复制,最快
559. new
560. array3.addAll(array1);
561. new
562.
563. // 克隆,次快
564. new
565. array4 = (ArrayList<Integer>) array1.clone();
566. new
567. 0, 4);
568. "array1[0]=" + array1.get(0));
569. "array4[0]=" + array4.get(0));
570.
571. }
572.
573. /*
574. * 复制Map最好用逐个复制最快,putAll最简单
575. * @author yifangyou
576. * @since 2011-08-16 09:35:00
577. */
578. static void
579. int maxlen = 1000000;
580. new
581. new
582. new
583. new
584. for (int i = 0; i < maxlen; i++) {
585. map1.put(i, i);
586. }
587.
588. long
589. // 逐个复制,最快
590. new
591. Set<Integer> key = map1.keySet();
592. for
593. Integer k = (Integer) it.next();
594. map2.put(k, map1.get(k));
595. }
596. new
597.
598. // 批量复制,最慢
599. new
600. map3.putAll(map1);
601. new
602. "map2[9999]=" + map2.get(9999));
603. "map3[9999]=" + map3.get(9999));
604.
605. // 逐个复制,次快
606. new
607. Set<Map.Entry<Integer, Integer>> set = map1.entrySet();
608. for
609. .hasNext();) {
610. Map.Entry<Integer, Integer> entry = (Map.Entry<Integer, Integer>) it
611. .next();
612. map4.put(entry.getKey(), entry.getValue());
613. }
614. new
615.
616. }
617.
618. }
转载于:https://blog.51cto.com/yifangyou/641251