V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
li00li
V2EX  ›  问与答

阿里巴巴面试 java 问题,有 1024 个字符串,用 subString 读取一万次可行么?说说原理

  •  1
     
  •   li00li · 2016-03-25 11:16:52 +08:00 · 2857 次点击
    这是一个创建于 3196 天前的主题,其中的信息可能已经有所发展或是发生改变。

    阿里巴巴面试 java 问题,有 1024 个字符串,用 subString 读取一万次可行么?说说原理

    有人可以详细的说一下么?

    9 条回复    2016-03-26 15:03:50 +08:00
    SpicyCat
        1
    SpicyCat  
       2016-03-25 11:39:44 +08:00
    题目没看懂。
    是说一个字符串长度是 1024 ,然后能不能执行 substring 方法一万次?
    Jelen
        2
    Jelen  
       2016-03-25 11:44:52 +08:00
    完全没看懂这题
    incompatible
        3
    incompatible  
       2016-03-25 12:02:41 +08:00   ❤️ 1
    substring 会生成新的字符串。由于 java.lang.String 的特殊性,每个生成的字符串都会在永久代里产生一个字符串常量(当一万次调用每次采用的都是不同的 startIndex 和 endIndex 时)。如果启动 jvm 时为永久代分配的空间不够多,那么就会产生 OutOfMemoryError

    所以我猜这道题考察的主要是 String 的 intern 以及 jvm 内存模型方面的知识。

    ps :以上是针对 jdk6 来说的。 jdk7 和 jdk8 中的变化可以参考下面这个文章:
    http://java-performance.info/string-intern-in-java-6-7-8/
    incompatible
        4
    incompatible  
       2016-03-25 12:13:58 +08:00   ❤️ 1
    抱歉,以上关于 String.substring()会在永久代产生字符串常量的说法是错误的。 substring 只会在堆内分配新空间,不会在永久代分配空间。
    Infernalzero
        5
    Infernalzero  
       2016-03-25 13:49:13 +08:00   ❤️ 2
    首先得看是 jdk6 还是 7
    不同的版本 subString 方法的实现是不同的
    6 里面 subString 会保存原 String 对象的引用,如果大字符串截取少量 String 会浪费很多内存
    7 里面就是用 Arrays.copyOfRange 了
    主要就是看 public String(char value[], int offset, int count)这个构造方法
    总之,具体得看使用场景了,根据要截取的字符串大小和原字符串的比较来判断用哪种方式
    Fred84
        6
    Fred84  
       2016-03-25 14:14:29 +08:00
    假设 1024 个字符串的对象为 a ,每次调用 a.substring 返回的字符串对象会保留 a 对象内存的引用(详见 substring 源码),如果调用了 1 万次,每次调用完毕后没有及时释放(比如你把这些对象都放在一个全局容器中),那么很可能会出现 OOM 的错误。
    li00li
        7
    li00li  
    OP
       2016-03-25 14:21:10 +08:00
    @SpicyCat 其实我当时也没有太懂
    li00li
        8
    li00li  
    OP
       2016-03-25 14:21:44 +08:00
    @incompatible 谢谢
    SoloCompany
        9
    SoloCompany  
       2016-03-26 15:03:50 +08:00
    你说 intern 会进入 PermGen/MetaSpace 还好理解, substring 甚至是 new String 就是个普通对象操作和 PermGen/MetaSpace 有什么直接关联吗, 唯一有的坑仅仅是 Java 7 开始 substring 的实现不再是 o(0) 而是有了 o(n) 的复制, 因为委员会认为这一点点复制的性能消耗在大多数情况下基本可以忽略, 为了避免对一个很大的字符串进行 substring 的时候因为保留着源字符串内部缓冲区的引用而无法释放内存而可能产生的问题, 并且这个选择是无法由 API 的使用者自己区决定的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2983 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 13:48 · PVG 21:48 · LAX 05:48 · JFK 08:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.