使用String.subString()方法的时候注意内存溢出的问题
public static void testH() { List<String> strings = new ArrayList<String>(); for (int i = 0; i < 1000; i++) { HugeStr h = new HugeStr(); // ImprovedHugeStr h = new ImprovedHugeStr(); strings.add(h.getSubString(1, 5)); } } static class HugeStr { private String str = new String(new char[10000]); String getSubString(int begin, int end) { return str.substring(begin, end); //会内存溢出 } } static class ImprovedHugeStr { private String str = new String(new char[10000]); String getSubString(int begin, int end) { return new String(str.substring(begin, end)); //返回的新String,没有溢出 } }
三种分隔字符串的方法,split()简单性能最差,StringTokenizer性能次之,自定义的方法性能最好但是可读性太低。建议StringTokenizer
static String initOrgStr() { StringBuffer sb = new StringBuffer(); for (int i = 0; i < 1000; i++) { sb.append(i); sb.append(":"); } return sb.toString(); } static void normalSplidTest() { String orgStr = initOrgStr(); for (int i = 0; i < 10000; i++) { orgStr.split(";"); } } static void stringTokenizerTest() { String orgStr = initOrgStr(); StringTokenizer st = new StringTokenizer(orgStr, ":"); for (int i = 0; i < 10000; i++) { while (st.hasMoreElements()) { st.nextElement(); } st = new StringTokenizer(orgStr, ":"); } } static void selfSplidTest() { String orgStr = initOrgStr(); String tmp = orgStr; for (int i = 0; i < 10000; i++) { while (true) { String splitStr = null; int j = tmp.indexOf(":"); if (j < 0) { break; } splitStr = tmp.substring(0, j); tmp = tmp.substring(j + 1); } tmp = orgStr; } }
String的charAt()和jindexOf()性能都特别的好,charAt连用甚至比startWith()、endWith()还快。
StringBuilder和StringBuffer:String在使用 “+”的时候,如果 + 的是具体的字符串,也就是编译期可知的,那么在编译期就已经完成了优化,只有最后的一个大字符串。
String result = "String" + "and" + "String"
// 反编译后只有这一个大字符串
String result = "StringandString"
StringBuilder.append还是会按照代码的顺序执行,依次append。
StringBuilder sb = 呢我StringBuilder() sb.append("String"); sb.append("and"); sb.append("String");
如果编译期不可知,最终也是用StringBuilder进行优化。
String str1 = "String"; String str2 = "and"; String str3 = "String"; String result = str1 + str2 + str3;
//反编译
String s = (new StringBuilder(String.valueOf(str1))).append(str2).append(str3).toString();
如果超大的字符串,String的 + ,被反编译StringBuilder实现,但是每次都会生成新的 StringBuilder。String的 + 最差,concat次之,StringBuilder最好。
static void hugeStr() { String s = ""; for (int i = 0; i < 10000; i++) { s += i; } String result = ""; for (int i = 0; i < 10000; i++) { result = result.concat(String.valueOf(i)); } StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000; i++) { sb.append(i); } }
StringBuffer线程安全,StringBuilder线程不安全。如果单线程StringBuilder会比StringBuffer好些。
如果知道字符串会有多大,在初始化的时候给定值,性能会更好。
public StringBuilder(int capacity) public StringBuffer(int capacity)
ArrayList、Vector:Vector线程安全。其他几乎一样。LinkedList使用双向连表。
如果list对象需要经常在任意位置插入元素,可以考虑使用LinkList代替ArrayList。但是LinkList从中间删除元素会特别耗时,它是遍历所有,找到具体的位置,在移除。
ArrayList和LinkList三种遍历方法。foreach和迭代器两种差不多,for循环LinkedList不要用,慢到你无法想象。迭代器会更好些,foreach最终也会解析成迭代器还多了一步没用的复制语句所以性能差一些。
static void eachList(List<String> list) { String tmp; for (String s : list) { tmp = s; } for (Iterator<String> it = list.iterator(); it.hasNext();) { tmp = it.next(); } int size = list.size(); for (int i = 0; i < size; i++) { tmp = list.get(i); } }
Map
HashMap:它最重要的就是原理了。理解原理。
LinkedHashMap:在HashMap的基础上加了一个链表存放顺序。accessOrder为true按照元素最后访问时间顺序,为false按照存入顺序,默认false。
public LinkedHashMap(int initialCapacity, folat loadFactor, boolean accessOrder)
可以修改accessOrder看看顺序
static void mapTest() { LinkedHashMap<Integer, String> map = new LinkedHashMap<>(16, 0.75F, false); map.put(3, "k"); map.put(1, "f"); map.put(2, "z"); map.put(7, "z"); map.put(8, "z"); map.put(6, "z"); map.put(4, "z"); map.put(5, "z"); map.get(8); map.get(7); map.get(6); for (Iterator<Integer> iterator = map.keySet().iterator(); iterator.hasNext();) { Integer key = (Integer) iterator.next(); System.out.println(key); } }
TreeMap:这个就nb了,根据key排序。想使用这个或者在 new TreeMap(Comparator<? super K> comparator)创建的时候指定Comparator,或者key实现了Comparable接口。
static void treeMapTest() { Map<Integer, String> map = new TreeMap<>(); map.put(3, "k"); map.put(1, "f"); map.put(2, "z"); map.put(7, "z"); map.put(8, "z"); map.put(6, "z"); map.put(4, "z"); map.put(5, "z"); for (Iterator<Integer> iterator = map.keySet().iterator(); iterator.hasNext();) { Integer key = (Integer) iterator.next(); System.out.println(key); } Map map2 = ((TreeMap) map).subMap(1, 4); System.out.println("get the key more than or equal 1 and less than 4"); for (Iterator<Integer> iterator = map2.keySet().iterator(); iterator.hasNext();) { Integer key = (Integer) iterator.next(); System.out.println(key); } // 小于2的 Map map3 = ((TreeMap) map).headMap(2); // 大于2的 Map map4 = ((TreeMap) map).tailMap(2); }