String的trim()方法是使用频率频率很高的一个方法,直到不久前我不确定trim去除两端的空白符时对换行符是怎么处理的点进去看了下源码的实现,才发现String#trim的实现跟我想像的完全不一样,原来一直以来我对这个函数存在着很深的误解。

我想的trim方法是类似于下面这样的:

package cc11001100.trimStudy;

/**
* @author CC11001100
*/
public class CustomString { private char[] values; public CustomString(char[] values) {
this.values = values;
} // ... public CustomString trim() {
char[] localValues = values;
int left = 0, right = localValues.length;
while (left < right && isBlankChar(localValues[left])) {
left++;
}
while (right > left && isBlankChar(localValues[right - 1])) {
right--;
}
if (left != 0 || right != localValues.length) {
char[] newValue = new char[right - left];
System.arraycopy(localValues, left, newValue, 0, newValue.length);
return new CustomString(newValue);
} else {
return this;
}
} private boolean isBlankChar(char c) {
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
} @Override
public String toString() {
return new java.lang.String(values);
} // ... }

即去除字符串两边的回车换行、制表符、回车换行符等等,然而String#trim的实际实现是这样的:

/**
* Returns a string whose value is this string, with any leading and trailing
* whitespace removed.
* <p>
* If this {@code String} object represents an empty character
* sequence, or the first and last characters of character sequence
* represented by this {@code String} object both have codes
* greater than {@code '\u005Cu0020'} (the space character), then a
* reference to this {@code String} object is returned.
* <p>
* Otherwise, if there is no character with a code greater than
* {@code '\u005Cu0020'} in the string, then a
* {@code String} object representing an empty string is
* returned.
* <p>
* Otherwise, let <i>k</i> be the index of the first character in the
* string whose code is greater than {@code '\u005Cu0020'}, and let
* <i>m</i> be the index of the last character in the string whose code
* is greater than {@code '\u005Cu0020'}. A {@code String}
* object is returned, representing the substring of this string that
* begins with the character at index <i>k</i> and ends with the
* character at index <i>m</i>-that is, the result of
* {@code this.substring(k, m + 1)}.
* <p>
* This method may be used to trim whitespace (as defined above) from
* the beginning and end of a string.
*
* @return A string whose value is this string, with any leading and trailing white
* space removed, or this string if it has no leading or
* trailing white space.
*/
public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */ while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

会将字符串两侧小于空格的字符都去除掉,这里可以简单的将\u005Cu0020理解为ASCII 0x20,即十进制的32,在ASCII码表中小于等于32的字符都将被去除:

先来看一下trim必须要去除的几个字符:

\t是9

\r是13

\n是10

这几个字符倒是都小于空格,而且前31位都是不可见字符,32是空格,这样做的话好像也没有太大的毛病,只是以后再使用trim的时候要想一下自己的数据有没有可能出现小于32不是空格制表符换行之类又需要保留的。

下面是对String#trim的一个简单测试:

package cc11001100.trimStudy;

/**
* @author CC11001100
*/
public class TrimStudy { public static void main(String[] args) { StringBuilder sb = new StringBuilder();
for (int i = 0; i < 128; i++) {
sb.append((char) i);
}
String s = sb.toString().trim();
// trim效果
System.out.println("-" + s + "-");
// trim之后第一个字符的ASCII码
System.out.println((int) s.charAt(0));
// 删除
System.out.println((char) 127);
// 查看其它空白字符的打印效果
System.out.println(sb.toString()); } }

运行结果:

注意ASCII 127删除字符应该也可以算作是不可见的空白字符。

后来我不死心,又去找了被依赖超多次数的Apache commons-lang中StringUtils#trim的实现:

/**
* <p>Removes control characters (char &lt;= 32) from both
* ends of this String, handling <code>null</code> by returning
* <code>null</code>.</p>
*
* <p>The String is trimmed using {@link String#trim()}.
* Trim removes start and end characters &lt;= 32.
* To strip whitespace use {@link #strip(String)}.</p>
*
* <p>To trim your choice of characters, use the
* {@link #strip(String, String)} methods.</p>
*
* <pre>
* StringUtils.trim(null) = null
* StringUtils.trim("") = ""
* StringUtils.trim(" ") = ""
* StringUtils.trim("abc") = "abc"
* StringUtils.trim(" abc ") = "abc"
* </pre>
*
* @param str the String to be trimmed, may be null
* @return the trimmed string, <code>null</code> if null String input
*/
public static String trim(String str) {
return str == null ? null : str.trim();
}

然而也只是调用了String#trim,也不是我想象的那样….

看来我一直以来都对trim有着很深的误解,trim是编程中对字符串处理的一个比较通用的概念,也不知道其它语言的具体实现是怎样的。

.

Java笔记之java.lang.String#trim的更多相关文章

  1. java.lang.String.trim(), 不仅仅去掉空格

      由于我们处理的日志需要过滤一些空格,因此大部分处理日志的程序中都用到了java.lang.String.trim()函数.直到有一次遇到一个诡异的问题,某个包含特殊字符的字符串被trim后居然也为 ...

  2. 转 Java笔记:Java内存模型

    Java笔记:Java内存模型 2014.04.09 | Comments 1. 基本概念 <深入理解Java内存模型>详细讲解了java的内存模型,这里对其中的一些基本概念做个简单的笔记 ...

  3. 菜鸡的Java笔记 第十四 String 类常用方法

    /*String 类常用方法    将所有String类的常用方法全部记下来,包括方法名称,参数作用以及类型    一个成熟的编程语言,除了它的语法非常完善之外,那么也需要提供有大量的开发类库     ...

  4. java 笔记(4) —— java I/O 流、字节流、字符流

    Java中使用流来处理程序的输入和输出操作,流是一个抽象的概念,封装了程序数据于输入输出设备交换的底层细节.JavaIO中又将流分为字节流和字符流,字节流主要用于处理诸如图像,音频视频等二进制格式数据 ...

  5. 疯狂java笔记(七) - Java集合之Map

    Map是以键值对(key-value)的形式来存储数据的.而且Map不允许key的重复,通过Map存储key-value对时,只需要考虑key的存储就可以,key存储后value就会跟着key(完全可 ...

  6. Java笔记:Java集合概述和Set集合

    本文主要是Java集合的概述和Set集合 1.Java集合概述 1)数组可以保存多个对象,但数组长度不可变,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组 ...

  7. Java笔记:Java 流(Stream)、文件(File)和IO

    更新时间:2018-1-7 12:27:21 更多请查看在线文集:http://android.52fhy.com/java/index.html java.io 包几乎包含了所有操作输入.输出需要的 ...

  8. 菜鸡的Java笔记 简单JAVA 类的开发原则以及具体实现

    /*  现在要求定义一个雇员信息类 在这个类之中包含有雇员编号 姓名 职位 基本工资 佣金等信息    对于此时给定要求实际上就是描述一类事物,而这样的程序类在在java之中可以将其称为简单java类 ...

  9. java笔记--理解java类加载器以及ClassLoader类

    类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...

随机推荐

  1. .net转PHP从零开始-配置visual studio 2013 PHP开发环境php for visual studio

    作为一个.net开发者,一直在visual studio这款强大的编辑器宠爱下,其他编辑器都不会用,也用着不熟练.最近这不是转php吗,使用php编辑器很不爽,觉得还是用visual studio舒服 ...

  2. 通过拓展Function.prototype实现一个AOP

    AOP(面向切面的编程)主要是将一些与核心业务逻辑模块无关的功能抽离出来,这些功能通常包括日志统计,安全控制,或者是异常处理等等. 我们要做的就是拓展Function.prototype来“动态植入” ...

  3. PAT甲题题解-1056. Mice and Rice (25)-模拟题

    有n个老鼠,第一行给出n个老鼠的重量,第二行给出他们的顺序.1.每一轮分成若干组,每组m个老鼠,不能整除的多余的作为最后一组.2.每组重量最大的进入下一轮.让你给出每只老鼠最后的排名.很简单,用两个数 ...

  4. linux第七章笔记

    第七章 链接 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或拷贝)到存储器并执行.链接可以执行于编译时,也就是在源代码被翻译成机器代码时:也可以执行于加载时,也就 ...

  5. SSM 框架快速整合实例--学生查询

    一.快速准备 SSM 框架即 Spring 框架.SpringMVC 框架.MyBatis 框架,关于这几个框架的基础和入门程序,我前面已经写过几篇文章作为基础和入门介绍了.对于这 3 个框架还不熟悉 ...

  6. 我是一个程序猿 ——《不是书评 :<我是一只IT小小鸟>》有感

    读了刘未鹏先生的文章<不是书评 :<我是一只IT小小鸟>>,产生了诸多共鸣,更明白了不少道理. 首先是一个很平常的现象,进度条效应,在操作移动终端上的软件时,如果没有进度条,人 ...

  7. svn 创建主干 分支版本

    转载  https://www.cnblogs.com/dongzhiquan/p/5222018.html SVN分支与合并 一. 分支与合并的概念 二. SVN分支的意义 三. 如何创建分支与合并 ...

  8. 侧边导航栏css示例

    效果展示: html: <div class="sidebar"> <ul> <li>优先级 <ul> <li>< ...

  9. [转帖] 学习 Linux 大页的内存知识

    一.在解释什么情况下需要开启大页和为啥需要开启大页前先了解下Linux下页的相关的知识:以下的内容是基于32位的系统,4K的内存页大小做出的计算1)目录表,用来存放页表的位置,共包含1024个目录en ...

  10. OneZero第五次站立会议(2016.3.25)

    会议时间:2016年3月25日 12:45~12:57 会议成员:冉华,张敏,王巍,夏一鸣. 会议目的:汇报前一天工作,全体成员评论,确定会后修改内容. 会议内容:1.界面原型已经确定.(夏负责) 2 ...