【Java】单词倒序输出

  如何将一段单词倒序输出?把“Hello Java Hello China”变成“China Hello Java Hello”?

  看起来好像很简单,只需要把字符串先分割成单词,然后加入一个StringBuilder或者StringBuffer中,最后再使用toString方法即可,现在来实现一下:

/**
 * @author Frank
 * @create 2017/11/24
 * @description
 */
public class Test {
    public static void main(String[] args) {
        String src = "Hello Java Hello China";//需要处理的字符串
        String[] arr = src.split(" ");//按空格分割
        int length = arr.length;//计算数组长度
        StringBuilder sb = new StringBuilder(src.length());//新建一个StringBuilder对象
        for (int i=length-1;i>=1;i--){
                sb.append(arr[i]+" ");//将字符串依次加入StringBuilder中
        }
        sb.append(arr[0]);//最后一个单词不加空格
        System.out.println(sb.toString());//输出
    }
}

  因为是使用单线程,所以用StringBuilder的效率会高于StringBuffer,输出如下:

China Hello Java Hello

  好的,现在就完美的解决了问题。

  但事实上,通常并不是全用空格分隔开来的,而是有逗号,句号,引号等,那么这该如何处理呢?

  那就只能一个字符一个字符判断了,用charAt()来判断字符是否为逗号句号或者引号,空格,如果是的话就知道到了分隔点了,如果不是的话就加入一个临时的StringBuilder对象,代码如下:

/**
 * @author Frank
 * @create 2017/11/24
 * @description
 */
public class Test2 {
    public static void main(String[] args) {
        String src = "Hello Java,Hello China.";//需要处理的字符串
        StringBuilder tmp = new StringBuilder(20);//定义一个StringBuilder对象
        StringBuilder goal = new StringBuilder(src.length());//定义一个StringBuilder对象来存放最终要输出的信息
        char c;//定义一个字符变量
        for (int i=src.length()-1;i>=0;i--){
            c = src.charAt(i);//从后往前取字符
            if(c ==' ' || c == ',' || c == '.'){//判断是否为分隔字符
                goal.append(tmp);//如果是的话就把tmp加入到goal中来
                goal.append(c);//在把分隔字符也一起加入
                tmp.delete(0,tmp.length());//清空tmp
            }else {
                tmp.insert(0,c);//如果不是分隔字符,说明单词未完整,继续加入tmp中
            }
        }
        if (!tmp.equals("")){
            goal.append(tmp);//如果tmp中还有内容,在添加到goal中
        }
        System.out.println(goal.toString());//输出
    }
}

  输出如下:

.China Hello,Java Hello

  好像没什么问题了。  

  现在难度进一步升级,如果有一个20M的字符串,“Hello_,_China_..._Bye.”(...代表中间省略的部分),单词之间用空格隔开,现在需要把所有单词全部颠倒顺序,要求效率不能太低。不看这个20M的话,好像没什么难度,关键就在于这个20M,肯定不能像第一种方式用split分割,那样的话会创建一个很大的字符串数组,浪费很多空间。

  所以这里采用第二种方式。

  我们先随机生成一个字符串,然后再使用第二种方式进行处理:

/**
 * @author Frank
 * @create 2017/11/24
 * @description
 */
public class Test3 {
    public static void main(String[] args) {
        long time = 0;
        StringBuilder sb = new StringBuilder();
        //先生成一个比较大的字符串
        for (int i=0;i<10000000;i++){
            sb.append(i+" ");
        }
        System.out.println("字符串长度:"+sb.length());

        //开始计算时间
        time = System.currentTimeMillis();
        StringBuilder tmp = new StringBuilder(20);//定义一个StringBuilder对象存放临时数据
        StringBuilder goal = new StringBuilder(sb.length());//定义一个StringBuilder对象来存放最终要输出的信息
        char c;//定义一个字符变量
        for (int i=sb.length()-1;i>=0;i--){
            c = sb.charAt(i);//从后往前取字符
            if(c ==' '){//判断是否为分隔字符
                goal.append(tmp);//如果是的话就把tmp加入到goal中来
                goal.append(c);//在把分隔字符也一起加入
                tmp.delete(0,tmp.length());//清空tmp
            }else {
                tmp.insert(0,c);//如果不是分隔字符,说明单词未完整,继续加入tmp中
            }
        }
        if (!tmp.equals("")){
            goal.append(tmp);//如果tmp中还有内容,在添加到goal中
        }
        System.out.println(System.currentTimeMillis()-time);//输出运行时间
    }
}

  输出如下:

字符串长度:78888890
608

  608毫秒,速度还ok,生成字符串还是要花挺多时间的,因为一直要进行内存复制,如果在循环次数后再加一个0,就会内存不足了。。。。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3332)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
    at java.lang.StringBuilder.append(StringBuilder.java:136)
    at com.frank.string.test1.Test3.main(Test3.java:14)

  至此,本篇问题讨论完毕,如果有更好更快的方法,欢迎留言交流讨论。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏C/C++基础

C++ explicit禁止单参数构造函数隐式调用

C++中单参数构造函数是可以被隐式调用的,主要有两种情形会隐式调用单参数构造函数: (1)同类型对象的拷贝构造;即用相同类型的其它对象来初始化当前对象。 (...

24850
来自专栏追不上乌龟的兔子

[奇怪但有用的数据结构]Trie前缀树

想象一个这样的情景,有一个很大的字典包含了很多的单词,需要判断一个新单词是否在字典中,最直接也最快的办法就是使用哈希表了。现在添加一个条件,判断字典里是否存在单...

75180
来自专栏carven

浅谈闭包

闭包 – closure, 应该可以说是javascript的一个难点吧, 其实说难也不难, 只是因为没有真正一个权威的人/书去给他一个真正的定义。 不过,学编...

9900
来自专栏编程

Python函数基础

函数是一种设计工具,它能让程序员将复杂的系统分解为可管理的部件 函数用于将相关功能打包并参数化 在Python中可以创建4种函数 全局函数:定义在模块中 //...

21450
来自专栏源哥的专栏

BASE64编码

附录:BASE64编码的原理(节选自http://www.vbzx.net/ArticleView/vbzx_Article_View_1199.asp)

10640
来自专栏MyBlog

Effective.Java 读书笔记(1)静态工厂和构造方法

用户在获得类它本身的实例的时候,通常会想到的就是使用public的构造器,但是一个类可以提供一个public的工厂方法。 这种工厂方法简化了返回该类实例的静态...

10920
来自专栏醒者呆

正则表达式——Java程序员懂你

正则表达式 关键字:正则表达式,Pattern,Matcher,字符串方法,split,replace 前文书立下了一个flag,这里要把它完成,就是正则...

39250
来自专栏编程心路

你不知道的 equals 和 ==

i1 == i2 和 i1.equals(i2) 这两个都是 true,大多数人应该可以答对。后面的 i3 == i4 和 i3.equals(i4) 估计就...

9820
来自专栏CDA数据分析师

教你一招 | Python3新特性(一) :字符串

从python2转到python3的第一个问题就是字符串的问题,我花了些时间把我能想到的和字符串处理有关的东西都整理如下。 1、Python2的字符串编码 在p...

208100
来自专栏余林丰

Java中的Object、T(泛型)、?区别

因为最近重新看了泛型,又看了些反射,导致我对Object、T(以下代指泛型)、?产生了疑惑。 我们先来试着理解一下Object类,学习Java的应该都知道Obj...

283100

扫码关注云+社区

领取腾讯云代金券