java中的StringBuilder有啥用?啥时候用StringBuilder?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中的StringBuilder有啥用?啥时候用StringBuilder?相关的知识,希望对你有一定的参考价值。

看到有些代码里这样写 new StringBuilder().append("a").append("b").append("c");
为啥要这样写 用String str=""; str+"a"+"b"+"c"不是更简单吗?

String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
String S1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个
String S1 = “This is only a” + “ simple” + “test”; 其实就是:
String S1 = “This is only a simple test”; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:
String S2 = “This is only a”;
String S3 = “ simple”;
String S4 = “ test”;
String S1 = S2 +S3 + S4;
这时候 JVM 会规规矩矩的按照原来的方式去做
在大部分情况下 StringBuffer > String
StringBuffer
Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
在大部分情况下 StringBuilder > StringBuffer
java.lang.StringBuilde
java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
何时用StringBuffer、StringBuilder:
StringBuilder一般使用在方法内部来完成类似"+"功能,因为是线程不安全的,所以用完以后可以丢弃.StringBuffer要用在全局变量中
参考技术A String str="a"+"b"+"c"...你这个有4个对象。。
上面的 有一个对象。。。。追问

也就是说用下面的方法会更耗费主存?

追答

效率低。。。String是不可变的字符序列 你可以看下JAVA得API

参考技术B ……

java中的Map有啥用呢

Map的接口Map---实现Map
Map.Entry--Map的内部类,描述Map中的按键/数值对。
SortedMap---扩展Map,使按键保持升序排列
下面以HashMap为例。
public static void main(String args[])HashMap hashmap = new HashMap();
hashmap.put("Item0", "Value0");
hashmap.put("Item1", "Value1");
hashmap.put("Item2", "Value2");
hashmap.put("Item3", "Value3");
Set set = hashmap.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()Map.Entry mapentry = (Map.Entry) iterator.next();
System.out.println(mapentry.getkey() + "/" + mapentry.getValue());注意,这里Map的按键必须是唯一的,比如说不能有两个按键都为null。
如果用过它,就会知道它的用处了。
资料:java.util 中的集合类包含 Java 中某些最常用的类。 最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。 从概念上而言,您可以将 List 看作是具有数值键的 Map。 而实际上,除了 List 和 Map 都在定义 java.util 中外,两者并没有直接的联系。本文将着重介绍核心 Java 发行套件中附带的 Map,同时还将介绍如何采用或实现更适用于您应用程序特定数据的专用 Map。了解Map 接口和方法Java 核心类中有很多预定义的 Map 类。 在介绍具体实现之前,我们先介绍一下 Map 接口本身,以便了解所有实现的共同点。 Map 接口定义了四种类型的方法,每个 Map 都包含这些方法。 下面,我们从两个普通的方法(表1)开始对这些方法加以介绍。表1: 覆盖的方法。 我们将这 Object 的这两个方法覆盖,以正确比较 Map 对象的等价性。equals(Object o)比较指定对象与此 Map 的等价性hashCode()返回此 Map 的哈希码Map 构建Map 定义了几个用于插入和删除元素的变换方法(表2)。表2: Map 更新方法: 可以更改 Map 内容。clear()从Map 中删除所有映射remove(Object key)从Map 中删除键和关联的值put(Object key, Object value)将指定值与指定键相关联clear()从Map 中删除所有映射putAll(Map t)将指定 Map 中的所有映射复制到此 map尽管您可能注意到,纵然假设忽略构建一个需要传递给 putAll() 的 Map 的开销,使用 putAll() 通常也并不比使用大量的 put() 调用更有效率,但 putAll() 的存在一点也不稀奇。 这是因为,putAll() 除了迭代 put() 所执行的将每个键值对添加到 Map 的算法以外,还需要迭代所传递的 Map 的元素。 但应注意,putAll() 在添加所有元素之前可以正确调整 Map 的大小,因此如果您未亲自调整 Map 的大小(我们将对此进行简单介绍),则 putAll() 可能比预期的更有效。查看Map迭代Map 中的元素不存在直接了当的方法。 如果要查询某个 Map 以了解其哪些元素满足特定查询,或如果要迭代其所有元素(无论原因如何),则您首先需要获取该 Map 的“视图”。 有三种可能的视图(参见表3)所有键值对 — 参见 entrySet()所有键 — 参见 keySet()所有值 — 参见 values()前两个视图均返回 Set 对象,第三个视图返回 Collection 对象。 就这两种情况而言,问题到这里并没有结束,这是因为您无法直接迭代 Collection 对象或 Set 对象。要进行迭代,您必须获得一个 Iterator 对象。 因此,要迭代 Map 的元素,必须进行比较烦琐的编码Iterator keyValuePairs = aMap.entrySet().iterator();Iterator keys = aMap.keySet().iterator();Iterator values = aMap.values().iterator();值得注意的是,这些对象(Set、Collection 和 Iterator)实际上是基础 Map 的视图,而不是包含所有元素的副本。 这使它们的使用效率很高。 另一方面,Collection 或 Set 对象的 toArray() 方法却创建包含 Map 所有元素的数组对象,因此除了确实需要使用数组中元素的情形外,其效率并不高。我运行了一个小测试(随附文件中的 Test1),该测试使用了 HashMap,并使用以下两种方法对迭代 Map 元素的开销进行了比较:int mapsize = aMap.size();Iterator keyValuePairs1 = aMap.entrySet().iterator();for (int i = 0; i < mapsize; i++) Map.Entry entry = (Map.Entry) keyValuePairs1.next(); Object key = entry.getKey(); Object value = entry.getValue(); ...Object[] keyValuePairs2 = aMap.entrySet().toArray();for (int i = 0; i < rem; i++) Map.Entry entry = (Map.Entry) keyValuePairs2[i]; Object key = entry.getKey();
Profilers in Oracle JDeveloperOracle JDeveloper 包含一个嵌入的监测器,它测量内存和执行时间,使您能够快速识别代码中的瓶颈。 我曾使用 Jdeveloper 的执行监测器监测 HashMap 的 containsKey() 和 containsValue() 方法,并很快发现 containsKey() 方法的速度比 containsValue() 方法慢很多(实际上要慢几个数量级!)。 (参见图1 和图2,以及随附文件中的 Test2 类)。 Object value = entry.getValue(); ...此测试使用了两种测量方法: 一种是测量迭代元素的时间,另一种测量使用 toArray 调用创建数组的其他开销。 第一种方法(忽略创建数组所需的时间)表明,使用已从 toArray 调用中创建的数组迭代元素的速度要比使用 Iterator 的速度大约快 30%-60%。 但如果将使用 toArray 方法创建数组的开销包含在内,则使用 Iterator 实际上要快 10%-20%。 因此,如果由于某种原因要创建一个集合元素的数组而非迭代这些元素,则应使用该数组迭代元素。 但如果您不需要此中间数组,则不要创建它,而是使用 Iterator 迭代元素。表3: 返回视图的 Map 方法: 使用这些方法返回的对象,您可以遍历 Map 的元素,还可以删除 Map 中的元素。entrySet()返回Map 中所包含映射的 Set 视图。 Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素keySet()返回Map 中所包含键的 Set 视图。 删除 Set 中的元素还将删除 Map 中相应的映射(键和值)values()返回map 中所包含值的 Collection 视图。 删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)访问元素表4 中列出了 Map 访问方法。Map 通常适合按键(而非按值)进行访问。 Map 定义中没有规定这肯定是真的,但通常您可以期望这是真的。 例如,您可以期望 containsKey() 方法与 get() 方法一样快。 另一方面,containsValue() 方法很可能需要扫描 Map 中的值,因此它的速度可能比较慢。表4: Map 访问和测试方法: 这些方法检索有关 Map 内容的信息但不更改 Map 内容。get(Object key)返回与指定键关联的值containsKey(Object key)如果Map 包含指定键的映射,则返回 truecontainsValue(Object value)如果此 Map 将一个或多个键映射到指定值,则返回 trueisEmpty()如果Map 不包含键-值映射,则返回 truesize()返回Map 中的键-值映射的数目对使用 containsKey() 和 containsValue() 遍历 HashMap 中所有元素所需时间的测试表明,containsValue() 所需的时间要长很多。 实际上要长几个数量级! (参见图1 和图2,以及随附文件中的 Test2)。 因此,如果 containsValue() 是应用程序中的性能问题,它将很快显现出来,并可以通过监测您的应用程序轻松地将其识别。 这种情况下,我相信您能够想出一个有效的替换方法来实现 containsValue() 提供的等效功能。 但如果想不出办法,则一个可行的解决方案是再创建一个 Map,并将第一个 Map 的所有值作为键。
参考技术A

特点:该集合存储键(key)值(value)对,一对一对往里存,而且要保证键(key)的唯一性。

       Map集合和Set集合很像,其实Set集合底层就是使用了Map集合。

什么时候使用Map集合:

    当数据之间存在映射关系时,优先考虑Map集合。

Map集合常用共有方法

1.添加

V put(K key, V value):将指定的值与此映射中的指定键关联,添加键值对。

void putAll(Map<? extends K,? extends V> m):从指定映射中将所有映射关系复制到此映射中,批量添加键值对。

2.删除

void clear():从此映射中移除所有映射关系,清空所有键值对。

V remove(Object key):如果存在一个键的映射关系,则将其从此映射中移除,删除单个键值对。

3.判断

boolean containsKey(Object key):如果此映射包含指定键的映射关系(是否包含该键),则返回 true。

boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值(是否包含该值),则返回 true。

boolean isEmpty():如果此映射未包含键-值映射关系,该map集合为空,则返回 true。

4.获取

V get(Object key):返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

int size():返回此映射中的键-值映射关系(键值对)数。

Collection<V>values():返回此映射中包含的值的 Collection 视图(集合)。

重点取出方式:

Set<K> keySet():返回此映射中包含的键的 Set 视图(集合)。

Set<Map.Entry<K,V>> entrySet():返回此映射中包含的映射关系的 Set 视图(集合)。


希望对您有所帮助!~

以上是关于java中的StringBuilder有啥用?啥时候用StringBuilder?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的线程池有啥用?

java中的enum有啥用呢?

java中的Map有啥用呢

Java Build Path 中的 Order 和 Export 选项卡有啥用

Java 中的 Unsafe 魔法类,到底有啥用?

java中的toString啥意思?toString有啥用?