## Converting Strings to Number in Javascript: Pitfalls

There are many ways to convert a String to a Number. I can think of at least 5 ways to convert a string into a number!

``````parseInt(num); // default way (no radix)
parseInt(num, 10); // parseInt with radix (decimal)
parseFloat(num) // floating point
Number(num); // Number constructor
~~num //bitwise not
num / 1 // diving by one
num * 1 // multiplying by one
num - 0 // minus 0
+num // unary operator "+"
``````

Which one to use when? When? Why? This tip is an analysis of each one and it’s common pitfalls.

According to a couple benchmarks in JsPerf.com most browsers have optimal response for ParseInt. Although it may be the fastest, here are some common mistakes parseInt does:

``````parseInt('08') // returns 0 in some old browsers.
parseInt('44.jpg') // returns 44
``````

parseInt: Always use it with a radix = parseInt(num, 10), don’t use it if you don’t want it to guess from characters.

What about ParseFloat? It’s all good if you never handle hexadecimal numbers; for instance:

``````parseInt(-0xFF) // returns -255
parseInt("-0xFF") // returns -255
parseFloat(-0xFF) // returns -255
parseFloat("-0xFF") // returns 0
``````

(Note, a negative hexadecimal number in a string is a special case that will go funky town in your application if you are parsing it. Make sure to always check for NaN values in your app to avoid surprises)

Plus, it retains the problem as parseInt with characters in the number:

``````parseFloat('44.jpg') // returns 44
``````

**parseFloat: Be careful with hexadecimal numbers, don’t use it if you don’t want it to guess from characters.”

The next one is Bitwise not (~). You can use that to convert a string to an integer only, but it’s not for floating numbers. The good thing about it is that it will return “0” if a character appears.

``````~~1.23 // returns 1
~~"1.23" // returns 1
~~"23" // returns 23
~~"Hello world" // returns 0
``````

What is it doing? It’s “flipping” each bit, also known as the A1 complement of the number. You can use, but be aware that it’s storing integers, so don’t use it unless you are sure your number ranges between the values of a signed 32 bit integer (this is because in the spec it calls ToInt32).

Bitwise not, use it to ensure input doesn’t have a character in it, only for integers

What about Number? Number has the same problem that parse* in a way that it will try to figure it out which number you are giving to it:

``````Number("023") // returns 23
Number(023) // returns 19
``````

(Note, 023 is ACTUALLY an octal number. No matter what you do, it will return 19; goes the same for hexadecimal ones without double or single quotes)

Number was also one of the slowest outcomes in JsPerf.

Number, pretty much don’t use it

The last ones are unary operators.

``````"1.23" * 1 // returns 1.23
"0xFF" - 0 // returns 255
"0xFF.jpg" / 1 // returns NaN
+"023" // returns 23
``````

Unlike the others, unary operators will be really happy to throw you a `NaN` value if they see anything funky. They are my favorite way to convert numbers, because anything with a character shouldn’t be considered neither 0 or “guessed” according to how many digits it has. I pick most of the time the `+` operator because is the least confusing one. They don’t have the best performance though, although `-0` has been giving good results.

### Best way to convert string to a number?

Negative hexadecimal numbers are the only ones that break inside a string. Any other number should be first parsed into a String (through + “” for instance) and then parsed to a number with a unary operator or a parseInt with a radix. parseFloat takes advantage of performance, but can give you some numeric values where a `NaN` is more appropriate.

FROM HERE

## java String intern

What is String Interning ?

String Interning is a method of storing only one copy of each distinct String Value, which must be immutable.

In Java, `String` class has a `public` method `intern()` that returns a canonical representation for the string object. Java’s `String` class privately maintains a pool of strings, where `String` literals are automatically interned.

When the `intern()` method is invoked on a `String` object it looks the string contained by this `String` object in the pool, if the string is found there then the string from the pool is returned. Otherwise, this `String` object is added to the pool and a reference to this `String` object is returned.

The `intern()` method helps in comparing two `String` objects with `==` operator by looking into the pre-existing pool of string literals, no doubt it is faster than `equals()` method. The pool of strings in Java is maintained for saving space and for faster comparisons.Normally Java programmers are advised to use `equals()`, not `==`, to compare two strings. This is because `==` operator compares memory locations, while `equals()` method compares the content stored in two objects.

Why and When to Intern ?

Though Java automatically interns all Strings by default, remember that we only need to intern strings when they are not constants, and we want to be able to quickly compare them to other interned strings. The `intern() `method should be used on strings constructed with `new String()` in order to compare them by `==` operator.

### Chinese

8种基本类型的常量池都是系统协调的，`String`类型的常量池比较特殊。它的主要使用方法有两种：

• 直接使用双引号声明出来的`String`对象会直接存储在常量池中。
• 如果不是用双引号声明的`String`对象，可以使用`String`提供的`intern`方法。intern 方法会从字符串常量池中查询当前字符串是否存在，若不存在就会将当前字符串放入常量池中

# 二，jdk6 和 jdk7 下 intern 的区别

``````public static void main(String[] args) {
String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);

String s3 = new String("1") + new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
}``````

• jdk6 下`false false`
• jdk7 下`false true`

``````public static void main(String[] args) {
String s = new String("1");
String s2 = "1";
s.intern();
System.out.println(s == s2);

String s3 = new String("1") + new String("1");
String s4 = "11";
s3.intern();
System.out.println(s3 == s4);
}``````

• jdk6 下`false false`
• jdk7 下`false false`

#### 2，jdk7中的解释

• 在第一段代码中，先看 s3和s4字符串。`String s3 = new String("1") + new String("1");`，这句代码中现在生成了2最终个对象，是字符串常量池中的“1” 和 JAVA Heap 中的 s3引用指向的对象。中间还有2个匿名的`new String("1")`我们不去讨论它们。此时s3引用对象内容是”11″，但此时常量池中是没有 “11”对象的。
• 接下来`s3.intern();`这一句代码，是将 s3中的“11”字符串放入 String 常量池中，因为此时常量池中不存在“11”字符串，因此常规做法是跟 jdk6 图中表示的那样，在常量池中生成一个 “11” 的对象，关键点是 jdk7 中常量池不在 Perm 区域了，这块做了调整。常量池中不需要再存储一份对象了，可以直接存储堆中的引用。这份引用指向 s3 引用的对象。 也就是说引用地址是相同的。
• 最后`String s4 = "11";` 这句代码中”11″是显示声明的，因此会直接去常量池中创建，创建的时候发现已经有这个对象了，此时也就是指向 s3 引用对象的一个引用。所以 s4 引用就指向和 s3 一样了。因此最后的比较 `s3 == s4` 是 true。
• 再看 s 和 s2 对象。 `String s = new String("1");` 第一句代码，生成了2个对象。常量池中的“1” 和 JAVA Heap 中的字符串对象。`s.intern();` 这一句是 s 对象去常量池中寻找后发现 “1” 已经在常量池里了。
• 接下来`String s2 = "1";` 这句代码是生成一个 s2的引用指向常量池中的“1”对象。 结果就是 s 和 s2 的引用地址明显不同。图中画的很清晰。

• 来看第二段代码，从上边第二幅图中观察。第一段代码和第二段代码的改变就是 `s3.intern();` 的顺序是放在`String s4 = "11";`后了。这样，首先执行`String s4 = "11";`声明 s4 的时候常量池中是不存在“11”对象的，执行完毕后，“11“对象是 s4 声明产生的新对象。然后再执行`s3.intern();`时，常量池中“11”对象已经存在了，因此 s3 和 s4 的引用是不同的。
• 第二段代码中的 s 和 s2 代码中，`s.intern();`，这一句往后放也不会有什么影响了，因为对象池中在执行第一句代码`String s = new String("1");`的时候已经生成“1”对象了。下边的s2声明都是直接从常量池中取地址引用的。 s 和 s2 的引用地址是不会相等的。

#### 小结

• 将String常量池 从 Perm 区移动到了 Java Heap区
• `String#intern` 方法时，如果存在堆中的对象，会直接保存对象的引用，而不会重新创建对象。

# 三，使用 intern

## 1,intern 正确使用例子

``````static final int MAX = 1000 * 10000;
static final String[] arr = new String[MAX];

public static void main(String[] args) throws Exception {
Integer[] DB_DATA = new Integer[10];
Random random = new Random(10 * 10000);
for (int i = 0; i < DB_DATA.length; i++) {
DB_DATA[i] = random.nextInt();
}
long t = System.currentTimeMillis();
for (int i = 0; i < MAX; i++) {
//arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length]));
arr[i] = new String(String.valueOf(DB_DATA[i % DB_DATA.length])).intern();
}

System.out.println((System.currentTimeMillis() - t) + "ms");
System.gc();
}``````

2160ms

826ms

## 2，intern 不当使用

#### 1，根据 log4j 打印日志查找问题原因

• trace SLF4JLogger.
• trace AbstractLoggerWrapper:
• trace AsyncLogger
``````org/apache/logging/log4j/core/async/AsyncLogger.actualAsyncLog(RingBufferLogEvent)                sun.misc.Launcher\$AppClassLoader@109aca82            1            1ms    org.apache.logging.log4j.core.async.AsyncLogger@19de86bb
org/apache/logging/log4j/core/async/AsyncLogger.log(Marker, String, Level, Message, Throwable)    sun.misc.Launcher\$AppClassLoader@109aca82            1           61ms    org.apache.logging.log4j.core.async.AsyncLogger@19de86bb``````

`Log4jLogEvent.calcLocation()`的代码如下:

``````public static StackTraceElement calcLocation(final String fqcnOfLogger) {
if (fqcnOfLogger == null) {
return null;
}
boolean next = false;
for (final StackTraceElement element : stackTrace) {
final String className = element.getClassName();
if (next) {
if (fqcnOfLogger.equals(className)) {
continue;
}
return element;
}
if (fqcnOfLogger.equals(className)) {
next = true;
} else if (NOT_AVAIL.equals(className)) {
break;
}
}
return null;
}``````

`Thread.currentThread().getStackTrace();`native的方法:

``````public StackTraceElement[] getStackTrace() {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// optimization so we do not call into the vm for threads that
// have not yet started or have terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
StackTraceElement[] stackTrace = stackTraceArray[0];
// a thread that was alive during the previous isAlive call may have
// since terminated, therefore not having a stacktrace.
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// Don't need JVM help for current thread
return (new Exception()).getStackTrace();
}
}

\openjdk7\hotspot\src\share\vm\prims\jvm.h line:294:
\openjdk7\hotspot\src\share\vm\prims\jvm.cpp line:4382-4414:
\openjdk7\hotspot\src\share\vm\classfile\javaClasses.cpp line:1635-[1651,1654,1658]:

``````oop classname = StringTable::intern((char*) str, CHECK_0);
oop methodname = StringTable::intern(method->name(), CHECK_0);
oop filename = StringTable::intern(source, CHECK_0);``````

#### `com.alibaba.fastjson.parser.JSONScanner#scanFieldSymbol()`

``````if (ch == '\"') {
bp = index;
this.ch = ch = buf[bp];
strVal = symbolTable.addSymbol(buf, start, index - start - 1, hash);
break;
}``````

#### `com.alibaba.fastjson.parser.SymbolTable#addSymbol()`:

``````/**
* Constructs a new entry from the specified symbol information and next entry reference.
*/
public Entry(char[] ch, int offset, int length, int hash, Entry next){
characters = new char[length];
System.arraycopy(ch, offset, characters, 0, length);
symbol = new String(characters).intern();
this.next = next;
this.hashCode = hash;
this.bytes = null;
}``````

fastjson 中对所有的 json 的 key 使用了 intern 方法，缓存到了字符串常量池中，这样每次读取的时候就会非常快，大大减少时间和空间。而且 json 的 key 通常都是不变的。这个地方没有考虑到大量的 json key 如果是变化的，那就会给字符串常量池带来很大的负担。

[1.1.24版本的`com.alibaba.fastjson.parser.SymbolTable#addSymbol()` Line:113]代码

``````public static final int MAX_SIZE           = 1024;

if (size >= MAX_SIZE) {
return new String(buffer, offset, len);
}``````

# 引用：

## In JS

To convert a JSON text into an object, you can use the eval() function. eval() invokes the JavaScript compiler. Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure. The text must be wrapped in parens to avoid tripping on an ambiguity in JavaScript’s syntax.

var myObject = eval(‘(‘ + myJSONtext + ‘)’);

However JSON.parse is still recommended:

The eval function is very fast. However, it can compile and execute any JavaScript program, so there can be security issues. The use of eval is indicated when the source is trusted and competent. It is much safer to use a JSON parser. In web applications over XMLHttpRequest, communication is permitted only to the same origin that provide that page, so it is trusted. But it might not be competent. If the server is not rigorous in its JSON encoding, or if it does not scrupulously validate all of its inputs, then it could deliver invalid JSON text that could be carrying dangerous script. The eval function would execute the script, unleashing its malice.

To defend against this, a JSON parser should be used. A JSON parser will recognize only JSON text, rejecting all scripts. In browsers that provide native JSON support, JSON parsers are also much faster than eval. It is expected that native JSON support will be included in the next ECMAScript standard.

var myObject = JSON.parse(myJSONtext, reviver);

## in java Convert object to json

Using Gson is easy to do the conversion:

In my case, I just need to do simple string without nested object. So i just use Map in java. We can also passing complex object directly into the gson parser.

```
@RequestMapping(value = "/reviewEligibility/{dealId}", method = RequestMethod.GET)
@ResponseBody
public String reviewEligibility(@PathVariable("dealId") String dealId) throws Exception {
boolean isExpeditedEligible =  xxServices.checkExpeditedReviewEligibility(Long.parseLong(dealId));
boolean isLimitedEligible =  xxServices.checkLimitedReviewEligibility(Long.parseLong(dealId));

Map<String, String> resultMap = new HashMap<String, String>();
resultMap.put("Expedited", String.valueOf(isExpeditedEligible));
resultMap.put("Limited", String.valueOf(isLimitedEligible));
Gson gson = new Gson();
String result = gson.toJson(resultMap);
return result;

```

the rest service would return me : {“Expedited”:”false”,”Limited”:”false”}

## inputstream from/to string

Fast way I can think of is using the apache common api:

``````StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();``````

Copy method can either use Charset.forName(“UTF-8”) or take String “UTF-8” directly.

Or Even easier:

``String myString = IOUtils.toString(myInputStream, "UTF-8");``

Opposite:

`public` `class` `StringToStream {`

`    ``public` `static` `void` `main(String[] args) {`
`        ``String text = ``"Converting String to InputStream Example"``;`
`        `
`        ``/*`
`         ``* Convert String to InputStream using ByteArrayInputStream `
`         ``* class. This class constructor takes the string byte array `
`         ``* which can be done by calling the getBytes() method.`
`         ``*/`
`        ``try` `{`
`            ``InputStream is = ``new` `ByteArrayInputStream(text.getBytes(``"UTF-8"``));`
`        ``} ``catch` `(UnsupportedEncodingException e) {`
`            ``e.printStackTrace();`
`        ``}`
`    ``}`
`}`

## generate random alpha-numeric string in Java

````1. Manually generate: `
```static final String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static Random rnd = new Random();

String randomString( int len )
{
StringBuilder sb = new StringBuilder( len );
for( int i = 0; i < len; i++ )
sb.append( AB.charAt( rnd.nextInt(AB.length()) ) );
return sb.toString();
}```
```
```
```
```
`2. Dollar provides encapsulated methods for achieving it:`
```// "0123456789" + "ABCDE...Z"
String validCharacters = \$('0', '9').join() + \$('A', 'Z').join();

String randomString(int length) {
return \$(validCharacters).shuffle().slice(length).toString();
}

@Test
public void buildFiveRandomStrings() {
for (int i : \$(5)) {
System.out.println(randomString(12));
}
}
``````

it outputs something like that:

```DKL1SBH9UJWC
JH7P0IT21EA5
5DTI72EO6SFU
HQUMJTEBNF7Y
1HCR6SKYWGT7
```
```
```
```
```
```
`3. The easiest way is using Apache Common lang directly. ````

## Difference between StringTokenizer and split

`StringTokenizer` is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the `split`method of `String` or the `java.util.regex` package instead.

String.split() returns an array (String[]) and Tokenizer returns one token at a time.