• Java编程思想学习笔记——字符串


    前言

    字符串操作是计算机程序设计中最常见的行为。

    不可变String

    String对象是不可变的

    重载"+"与StringBuilder

    String对象是不可变的,可以给String对象加任意多得别名。
    String对象具有只读特性,所以指向它的任何引用都不可能改变它的值。

    String a = "a";
    String b = a;
    System.out.println("first: a=" + a + " b=" + b);
    b = "b";
    System.out.println("second: a=" + a + " b=" + b);
    

    运行结果:

    first: a=a b=a
    second: a=a b=b
    

    String对象的不可变性会带来一定的效率问题。
    比如为String对象重载的"+"操作符。

    重载:一个操作符在应用于特定类时,被赋予特殊的意义。Java中,用于String的"+"与"+="是仅有的两个重载过的操作符。Java不允许程序员重载任何操作符。

    public class Connection {
        public static void main(String[] args) {
            String str = "hello";
            String anotherStr = "abc" + str + "def" + 123;
            System.out.println(anotherStr);
        }
    }
    
    Compiled from "Connection.java"
    public class Connection {
      public Connection();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: ldc           #2                  // String hello
           2: astore_1
           3: new           #3                  // class java/lang/StringBuilder
           6: dup
           7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
          10: ldc           #5                  // String abc
          12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          15: aload_1
          16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          19: ldc           #7                  // String def
          21: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          24: bipush        123
          26: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
          29: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          32: astore_2
          33: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
          36: aload_2
          37: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          40: return
    }
    

    无意识的递归

    Java中的每个类从根本上都是继承自Object。

    public class Object {
      ...
      //Object类的toString方法
      public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
       ...
    }
    

    标准容器类同样是继承自Object类,因此容器类都有toString()方法,并且覆写了这个方法来表达容器本身和它所包含的对象。
    比如ArrayList.toString()方法,查看源代码可知,ArrayList类继承自AbstractList类,而AbstractList类覆写了toString()方法。
    它会遍历AbstractList中所包含的所有对象,并调用每个元素上的toString方法。

    
    public abstract class AbstractCollection<E> implements Collection<E> {
      ...
     public String toString() {
            Iterator<E> it = iterator();
            if (! it.hasNext())
                return "[]";
    
            StringBuilder sb = new StringBuilder();
            sb.append('[');
            for (;;) {
                E e = it.next();
                sb.append(e == this ? "(this Collection)" : e);
                if (! it.hasNext())
                    return sb.append(']').toString();
                sb.append(',').append(' ');
            }
        }
    ...
    }
    

    想打印对象的内存地址,应该调用super.toString()方法,也就是基类Object的toString()方法。

    class A{
       public static void main(String [] args){
        System.out.println(new A());
      }
      @Override
      public void toString(){
         // return "A:"+this;//会造成递归调用,导致栈溢出。
          return "A:"+super.toString();
      }
    }
    
    

    正则表达式

    解决各种字符串处理相关的问题:匹配,选择,编辑以及验证。

    基础

    以某种方式来描述字符串

    Java中,表示:插入一个正则表达式的反斜线,它后面的字符具有特殊的意义。

    数字:\d
    反斜线:\\
    

    String类中的,正则匹配方法:
    1.匹配matches()方法。查看源代码,可以知道该方法实际上是调用了Pattern类的matches()方法来实现正则表达式的匹配功能的。
    2.分隔split()方法,这个方法能将字符串从正则表达式匹配的地方切开。
    3.替代replaceAll(),replaceFirst()方法

     ...
     public boolean matches(String regex) {
            return Pattern.matches(regex, this);
        }
     public String[] split(String regex, int limit) {
            /* fastpath if the regex is a
             (1)one-char String and this character is not one of the
                RegEx's meta characters ".$|()[{^?*+\", or
             (2)two-char String and the first char is the backslash and
                the second is not the ascii digit or ascii letter.
             */
            char ch = 0;
            if (((regex.value.length == 1 &&
                 ".$|()[{^?*+\".indexOf(ch = regex.charAt(0)) == -1) ||
                 (regex.length() == 2 &&
                  regex.charAt(0) == '\' &&
                  (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
                  ((ch-'a')|('z'-ch)) < 0 &&
                  ((ch-'A')|('Z'-ch)) < 0)) &&
                (ch < Character.MIN_HIGH_SURROGATE ||
                 ch > Character.MAX_LOW_SURROGATE))
            {
                int off = 0;
                int next = 0;
                boolean limited = limit > 0;
                ArrayList<String> list = new ArrayList<>();
                while ((next = indexOf(ch, off)) != -1) {
                    if (!limited || list.size() < limit - 1) {
                        list.add(substring(off, next));
                        off = next + 1;
                    } else {    // last one
                        //assert (list.size() == limit - 1);
                        list.add(substring(off, value.length));
                        off = value.length;
                        break;
                    }
                }
                // If no match was found, return this
                if (off == 0)
                    return new String[]{this};
    
                // Add remaining segment
                if (!limited || list.size() < limit)
                    list.add(substring(off, value.length));
    
                // Construct result
                int resultSize = list.size();
                if (limit == 0) {
                    while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                        resultSize--;
                    }
                }
                String[] result = new String[resultSize];
                return list.subList(0, resultSize).toArray(result);
            }
            return Pattern.compile(regex).split(this, limit);
        }
        public String replaceFirst(String regex, String replacement) {
            return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
        }
        public String replaceAll(String regex, String replacement) {
            return Pattern.compile(regex).matcher(this).replaceAll(replacement);
        }
     ...
    

    创建正则表达式

    ![http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html]

    量词

    1.贪婪型
    2.占有型
    3.勉强型

    CharSequence
    接口CharSequence从CharBuffer,String,StringBuffer,StringBuilder类之中抽象出字符序列的的一般化定义:

    interface CharSequence{
       charAt(int i);
       length();
       subSequence(int start,int end);
       toString();
    }
    

    Pattern和Matcher

    String类功能有限,我们可以自己构造强大的正则表达式对象。
    导入java.util.regex包,使用静态方法Pattern.compile()来编译正则表达式。

      public static Pattern compile(String regex) {
            return new Pattern(regex, 0);
        }
    
    

    compile()方法返回一个Pattern对象,表示编译后的正则表达式。

      public Matcher matcher(CharSequence input) {
            if (!compiled) {
                synchronized(this) {
                    if (!compiled)
                        compile();
                }
            }
            Matcher m = new Matcher(this, input);
            return m;
        }
    

    对于已编译正则表达式的Pattern对象的matcher()方法,加上要被匹配的字符串,返回一个Matcher对象。
    使用Matcher对象的各种方法,我们就能判断各种不同类型的匹配是否成功。

    boolean matches() //判断整个字符串是否匹配
    boolean lookingAt()//判断字符串的起始部分是否能够匹配
    boolean find()
    boolean find(int start)
    
  • 相关阅读:
    HTML清除浮动的几种形式
    HTML和XML的区别
    CSS选择器的优先级
    CSS选择器
    PHP单文件和多文件的上传(示例)
    单元测试
    定义person类及其子类,并按要求设计、定义和实例化类 (实例)
    CSS的 行内元素 和 块类元素
    小心了!Kubernetes自动化操作工具将让你失去工作
    开源云计算厂商:浅析渠道激活平台的打造
  • 原文地址:https://www.cnblogs.com/JohnTsai/p/4796328.html
Copyright © 2020-2023  润新知