Nivelle 开拓视野冲破艰险看见世界 身临其境贴近彼此感受生活

java基础(十二)之字符串

2017-06-10
nivelle

字符串

String 对象时不可变的.String中每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,以包含修改后的字符串内容.最初的String对象没有丝毫修改.

public class Immutable {
  public static String upcase(String s){
    return s.toUpperCase();
  }
  public static void main(String args[]){
    String q="howdy";
    System.out.println(q);
    String qq=upcase(q);
    System.out.println(qq);
    System.out.println(q);
  }
}


当把q传递给upcase()方法是,实际传递的是引用的一个拷贝,其实,每当把String对象作为方法参数时,都会复制一份引用,而该引用所指对象其实一直待在单一的物理位置上,从未动过.

重载”+”与StringBuilder

string对象时不可变的,你可以给一个String对象加任意多的别名.因为String对象具有只读性,所以指向它的任何引用都不可能改变它的值,因此,也就不会对其他的引用有什么影响.

当为一个类编写toString()方法时,如果字符串操作比较简单,那就可以信赖编译器,它会为你合理地构造最终字符串结果.但是,如果要在toString()方法中使用循环,哪最好自己创建一个StringBuilder对象,用它来构造最终结果.StringBuilder允许为你预先指定大小,如果已经知道最终的字符串大概多长,哪预先指定StringBuilder的大小可以避免多次重新分配缓冲.

public class UsingStringBuilder {

  public static Random rand = new Random();

  StringBuilder result = new StringBuilder("[");

  public String toString() {

    for (int i = 0; i < 25; i++)

    {
      result.append(rand.nextInt(100));

      result.append(", ");
    }

    result.delete(result.length() - 2, result.length());

    result.append("]");

    return result.toString();
  }

  public static void main(String args[]) {

    UsingStringBuilder usb = new UsingStringBuilder();

    System.err.println(usb);

  }
}


StringBuilder提供了丰富而全面的方法,包括inser(),repleace(),substring()甚至reverse()当时最常见的还是append()和toString().还有delete()方法,用于删除字符.

无意识递归

public class InfiniteRecursion {

  public String toStirng() {

    return "InfiniteRecursion address :" + this + "\n";

  }

  public static void main(String args[]) {

    List<InfiniteRecursion> v = new ArrayList<>();

    for (int i = 0; i < 10; i++) {

      v.add(new InfiniteRecursion());

    }

    System.out.println(v);

  }

}


容器类都有toString()方法,并且覆盖了该方法,使得生成的String结果能够表达容器自身,以及容器所包含的对象.例如ArrayList.toString()它会遍历ArrayList中包含的所有对象,调用每个元素上的toString()方法.

这里发生了自动类型转换,由IntiniteRecursion类型转换成String类型.因为编译器看到一个String对象后面跟着一个”+”,而后面的对象不是String,于是编译器试着将this转换成一个String.它正是通过调用this上的toString()方法,于是就发生了递归调用.

如果真想打印对象内存地址,应该调用Object.toString()方法,这才是负责人方法,所以应该调用super.toString().

String上的操作


public class StringTest {
   
   public static void main(String[] args) {
    char charArray [] = new char[3];
    String str ="abcdefghijklmnopqrsruvw";
    String str1 ="abcdefghijklmnopqrsruvw";
    System.out.println("str长度:"+str.length());
    System.out.println("某个索引上的字符:"+str.charAt(0));
    //System.out.println("复制char或byte到一个目标数组中:"+str.getChars(0, str.length()-1, charArray , 0));
    System.out.println("生成一个char[]:"+str.toCharArray());
    System.out.println("比较字符串内容:"+str.equalsIgnoreCase(str));
    System.out.println("按字典顺序比较字符串内容:"+str.compareTo(str));
    System.out.println("字符串内容是否包含参数内容:"+str.concat("s"));
    System.out.println("字符串内容整个内容是否相等:"+str.contentEquals(str));
    System.out.println("字符是否相等,忽略大小写:"+str.equalsIgnoreCase(str));
    //regionMatches(int toffset,String other,int ooffset,int len); 
    System.out.println("两个字符串是否一样长:"+str.regionMatches(1, str1, 1, 5));
    System.out.println("是否以某个字符开头:"+str.startsWith("a"));
    System.out.println("是否以某个字符结尾:"+str.endsWith("w"));
    System.out.println("是否以某个字符结尾:"+str.endsWith("w"));
    System.out.println("某个字符的索引:"+str.indexOf("a"));
    System.out.println("某个字符的索引,从后开始索引:"+str.lastIndexOf("w"));
    System.out.println("子字符串:"+str.substring(2));
    System.out.println("拼接字符串:"+str.concat("nivelle"));
    System.out.println("替换字符串:"+str.replace("abcd", "fuxinzhong"));
    System.out.println("转成大写字母:"+str.toUpperCase());
    System.out.println("去掉空白字符:"+str.trim());
    System.out.println("返回表示参数内容的String:"+str.valueOf(345));
    System.out.println("为每个唯一的字符序列生成一个且仅生成一个String:"+str.intern());
  }
}

结果:

str长度:23 某个索引上的字符:a 生成一个char[]:[C@7de534cb 比较字符串内容:true 按字典顺序比较字符串内容:0 字符串内容是否包含参数内容:abcdefghijklmnopqrsruvws 字符串内容整个内容是否相等:true 字符是否相等,忽略大小写:true 两个字符串是否一样长:true 是否以某个字符开头:true 是否以某个字符结尾:true 是否以某个字符结尾:true 某个字符的索引:0 某个字符的索引,从后开始索引:22 子字符串:cdefghijklmnopqrsruvw 拼接字符串:abcdefghijklmnopqrsruvwnivelle 替换字符串:fuxinzhongefghijklmnopqrsruvw 转成大写字母:ABCDEFGHIJKLMNOPQRSRUVW 去掉空白字符:abcdefghijklmnopqrsruvw 返回表示参数内容的String:345 为每个唯一的字符序列生成一个且仅生成一个String:abcdefghijklmnopqrsruvw


格式化输出

java中,所有的格式化功能都由java.util.Formatterl类处理.可以将其看作一个翻译器,它将你的格式化字符串与数据翻译成需要的结果.

public class Turtle {

  private String name;

  private Formatter f;

  public Turtle(String name, Formatter f) {

    this.name = name;

    this.f = f;

  }

  public void move(int x, int y) {

    f.format("%s the turtle is at (%d,%d)\n", name, x, y);

  }

  public static void main(String args[]) {

    PrintStream outAlias = System.out;

    Turtle tommy = new Turtle("Tommy", new Formatter(System.out));

    Turtle terry = new Turtle("terry", new Formatter(outAlias));

    tommy.move(0, 0);

    terry.move(4, 8);

    tommy.move(3, 4);

    terry.move(2, 5);

    tommy.move(3, 3);

    terry.move(3, 3);

  }

}


Tommy the turtle is at (0,0) terry the turtle is at (4,8) Tommy the turtle is at (3,4) terry the turtle is at (2,5) Tommy the turtle is at (3,3) terry the turtle is at (3,3)

Formatter的构造器经过重载可以接受多种输出目的地,不过最常用的还是PrintStream(),OutputStream()和File.

格式化说明符

在插入数据时,如果想控制空格与对齐,你需要更精细的格式化修饰符.抽象语法:

%[argument_index$][flags][width][.precision]conversion

最常见的应用是控制一个域的最小尺寸,这可以通过指定width来实现.Formatter对象通过在必要时添加空格,来确保一个域至少达到某个长度.在默认情况下,数据是左右对齐,不过可以通过使用”-“标志来改变对齐方向.

与width相对的是precision,它用来指明最大尺寸.width可应用于各种类型的数据转换,并且其行为方式都一样.precision则不然,不是所有数据类型都可使用precision,而且不同的precision应用不同的数据类型,意义也不同.应用String时,表示输出的字符的最大数量.而应用浮点数时,表示小数部分要显示出来的位数,如果小数位数过多则舍入,太少则在尾部补零.无法应用于整数.

public class Receipt {

  private double total=0;

  private Formatter f =new Formatter(System.out);

  public void printTitle(){

    f.format("%-15s %5s %10s\n", "Item","Qty","Price");

    f.format("%-15s %5s %10s\n", "---","---","---");

  }
  
  public void print(String name,int qty,double price){

    f.format("%-15.15s %5d %10.2f\n", name,qty,price);

    total+=price;

  }
  
  public void printTotal(){

    f.format("%-15s %5s %10.2f\n", "Tax","",total*0.06);

    f.format("%-15s %5s %10s\n", "","","----");

    f.format("%-15s %5s %10.2f\n", "Total","",total*1.06);

  }
  
  public static void main(String args[]){

    Receipt receipt = new Receipt();

    receipt.printTitle();

    receipt.print("Jack's magic beans", 4, 4.25);

    receipt.print("Princess peas", 3, 5.1);

    receipt.print("Three bears porridge", 1, 14.29);

    receipt.printTotal();

  }
  
}

结果:

Item Qty Price — — — Jack’s magic be 4 4.25 Princess peas 3 5.10 Three bears por 1 14.29 Tax 1.42 —- Total 25.06


Formatter转换

类型转型字符:

d:整数型,c:Unicode字符,b:Boolean值,s:string,f:浮点数,e:浮点数(科学计数),x:整数(十六进制),h:散列码(十六进制),%:字符”%”

String.format()

它是一个static方法,它接收与Formatter.format()方法一样的参数,但返回一个String对象.当你只需要使用format()方法一次的时候,String.format()用起来很方便:


public class DatabaeException extends Exception {

  private static final long serialVersionUID = 1L;

  public DatabaeException(int transactionId, int querID, String message) {

    super(String.format("(t%d,q%d) %s", transactionId, querID, message));

  }

  public static void main(String args[]) {

    try {

      throw new DatabaeException(3, 7, "write failed");

    } catch (Exception e) {

      System.out.println(e);

    }

  }

}



结果:learn.String.DatabaeException: (t3,q7) write failed

正则表达式

基础

一般来说,正则表达式就是以某种方式来描述字符串,因此你可以说:如果一个字符串含有这些东西,那么它就是我正在找的东西.

java中,\的意思是:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义.例如:如果你想表示一位数字,那么正则表达式应该是\d.如果,想插入一个普通的反斜线,则应该\\.不过换行和制表符之类的东西只需要单反斜线:\n\t.

要表示,”一个或多个之前的表达式”,应该使用+.所以,如果要表示”可能有一个负号,后面跟着一位或多位数字”:

-?\\d


(string学习2)

(string学习1)


评论