Java中字符序列的替换与分解的几种实现方法

目录
  • 一、使用String类
  • 二、使用StringTokenizer类
  • 三、使用Scanner类
  • 四、使用Pattern类与Matcher类

一、使用String类

String对象调用public String replaceAll(String regex,String replacement)方法,返回一个新的String对象,返回的String对象的字符序列是把当前String对象的字符序列中,所有和参数regex相匹配的子字符序列替换成参数replacement指定的字符序列所得到的字符序列。

例如:

String s1="123hello456";
String s2=s1.replaceAll("\\d+","你好。"); //"\\d+"是正则表达式,表示一个或多个0~9之间的任意数字
System.out.println(s1);//打印结果为: 123hello456    没有被改变
System.out.println(s2);//打印结果为: 你好。hello你好。

再如:

String regex="-?[0-9][0-9]*[.]?[0-9]*";
String s1="999大家好,-123.459804明天放假了";
String s2=s1.replaceAll(regex,"");
System.out.println("剔除"+s1+"中的数字后得到的字符序列是:"+s2);
//剔除999大家好,-123.459804明天放假了中的数字后得到的字符序列是: 大家好, 明天放假了

其实,String类提供了一个实用的方法:

public String[] split(String regex)

当String对象调用该方法时,使用参数指定的正则表达式regex作为分隔标记,分解出String对象的字符序列中的单词,并将分解出的单词存放在String数组中。

例如:

//需求:对于一个字符序列,要分解出全部由数字字符组成的单词。
String s1="1931年9月18日晚,日本发动侵华战争,请记住这个日子!";
String regex="\\D+";
String s2[]=s1.split(regex);
for(String s:s2)
System.out.println(s);//分别输出1931  09  08 ,且可知s2.length()=3;

需要特别注意的是,split方法认为分隔标记的左右是单词,额外规则是,如果左面的单词是不含任何字符的字符序列,即为空,则这个字符序列仍然算成一个单词,但右边的单词必须是含有字符的字符序列。
例如:

String s1="公元2022年02月18日";
String regex="\\D+";
String s2[]=s1.split(regex);
System.out.println(s2.length());//会编译报错:Method call expected
for(String s:s2)
System.out.println(s);
//s2[0]=  s2[1]=2022 s2[2]=02  s2[3]=18  s1[0]是空的字符串,什么也不会显示。
//所以s2数组长度应该为4而不是3,多出来的空字符串是"公元"左侧被默认有一个单词。内容为空。

二、使用StringTokenizer类

1.和split()方法不同的是,StringTokenizer对象不使用正则表达式做分隔标记。
2.当分析一个字符序列并将字符序列分解成可被独立使用的单词时,可以使用java.util包中的StringTokenizer类,称该类的对象是一个字符序列的分析器,该类有两个构造方法。
构造方法1:StringTokenizer(String s):构造一个StringTokenizer对象,例如fenxi。fenxi使用的是默认的分隔标记(空格符,换行符,回车符,Tab符,进纸符(\f))分解出参数s的字符序列中的单词,即这些单词成为分析中的数据。
构造方法2:StringTokenizer(String s,String delim):构造一个StringTokenizer对象,例如fenxi。fenxi用参数delim的字符序列中的字符的任意排列作为分隔标记,分解出参数s的字符序列中的单词,即这些单词成为fenxi中的数据。
注意:分隔标记的任意排列仍然是分隔标记。
3.fenxi可以调用String nextToken()方法逐个获取fenxi中的单词,每当nextToken()返回一个单词,fenxi就会自动删除该单词。
4.fenxi可以调用boolean hasMoreTokens()方法返回一个boolean值,只要fenxi中还有单词,该方法就返回true,否则返回false。
5.fenxi可以调用countToken()方法返回当前fenxi中单词的个数。

具体示例1:

String s="we are stud,ents";
StringTokenizer fenxi=new StringTokenizer(s," ,");//用空格和逗号的任意组合作为分隔标记
int number=fenxi.countToken();
while(fenxi.hasMoreTokens()){
String str=fenxi.nextToken();
System.out.println(str);
System.out.println("还剩"+fenxi.countToken()+"个单词");
}
System.out.println("s共有单词:"+number+"个");
//输出结果:
we
还剩3个单词
are
还剩2个单词
stud
还剩1个单词
ents
还剩0个单词
s共有单词:4个

具体示例2:

String s="市话费:28.39元,长途话费:49.15元,上网费:352元";
String delim="[^0-9.]+";//非数字和.序列都匹配delim
s=s.replaceAll(delim,"#");
StringTokenizer fenxi=new StringTokenizer(s,"#");
double totalMoney=0;
while(fenxi.hasMoreTokens()){
double money=Double.parseDouble(fenxi.nextToken());
System.out.println(money);
totalMoney+=money;
}
System.out.println("总费用:"+totalMoney+"元");
//输出结果:
28.39
49.15
352.0
总费用:429.53999999999996元

三、使用Scanner类

为了创建一个Scanner对象,需要把一个String对象传递给所构造的Scanner对象,例如,对于:

String s="telephone cost 876 dollar.Computer cost 2398.89 dollar.";

为了解析出s的字符序列中的数字型单词,可以如下构造一个Scanner对象:

Scanner scanner=new Scanner(s);

那么scanner默认使用空格作为分隔标记来解析s的字符序列中的单词。也可以让scanner对象调用方法:

useDelimiter(正则表达式);

将正则表达式作为分隔标记,即Scanner对象在解析s的字符序列时,把与正则表达式匹配的字符序列作为分隔标记。
Scanner对象解析字符序列的特点如下:

  • scanner对象调用next()方法依次返回s的字符序列中的单词,如果最后一个单词已被next()方法返回,scanner对象调用hasNext()将返回false,否则返回true。
  • 对于s的字符序列中的数字型单词,例如,12.34等,scanner可以调用nextInt()或nextDouble()方法来代替next()方法。即scanner可以调用nextInt()或nextDouble()方法将数字型单词转化为int型或者double型数据返回。
  • 如果单词不是数字型单词,scanner调用nextInt()或nextDouble()方法,将会发生InputMismatchException异常,在处理异常时可以调用next()方法返回该非数字化单词。

具体示例:

String cost="市话费:28.39元,长途话费:49.15元,上网费:352元";
Scanner scanner=new Scanner(cost);
scanner.useDelimiter("[^0-9.]+");
double sum=0;
while(scanner.hasNext()){
try{
    double price=scanner.nextDouble();
    sum+=price;
    System.out.println(price);
    }catch(InputMismatchException e){
    String s=scanner.next();
    }
}
System.out.println("总费用:"+sum+"元");
//输出结果:
28.39
49.15
352.0
总费用:429.53999999999996元

对比:

1. StringTokenizer类和Scanner类都可用于分解字符序列中的单词,但是二者在思想上有所不同。

2. StringTokenizer类把分解出来的单词全都放入StringTokenizer对象的实体中,因此StringTokenizer对象能够快速的获得单词,即StringTokenizer对象的实体占用较多的内存(多占用内存,提升速度,相当于把单词记在大脑中)。

3. 与StringTokenizer类不同的是,Scanner类仅仅存放怎样获取单词的分隔标记,因此scanner对象获取单词的速度相对较慢,但scanner对象节省内存空间(减慢速度,节省空间,相当于把单词放在字典里,大脑只记忆查字典的规则)。

四、使用Pattern类与Matcher类

使用Pattern类与Matcher类的步骤如下:

1.使用正则表达式regex作为参数得到一个称为"模式"的Pattern类的实例pattern。例如

String regex="-?[0-9][0-9]*[.]?[0-9]*";
Pattern pattern=Pattern.compile(regex);

2.模式对象pattern调用matcher(CharSequence s)方法返回一个Matcher对象matcher,称为匹配对象,参数s是matcher要检索的String对象。

Matcher matcher=pattern.matcher(s);

3.这两个步骤结束后,匹配对象matcher就可以调用各种方法检索s。

具体方法有:

(1)public boolean find():寻找s的字符序列中和regex匹配的下一子序列。如果成功则返回true,否则返回false。matcher首次调用该方法时,寻找s中第一个和regex匹配的子序列,如果find方法返回true,则matcher再调用find方法时,就会从上一次匹配成功的子字符序列后开始寻找下一个匹配regex的子字符序列。另外,当find方法返回true时,matcher可以调用start()方法和end()方法得到子字符序列在s中的开始位置和结束位置。当find方法返回true时,matcher调用group()可以返回find方法本次找到的匹配regex的子字符序列。
(2)public boolean matches():matcher调用该方法判断s的字符序列是否完全和regex匹配。
(3)public boolean lookingAt():matcher调用该方法判断从s的字符序列的开始位置是否有和regex匹配的子字符序列。
(4)public boolean find(int start):matcher调用该方法判断s的字符序列从参数start指定位置开始是否有个regex匹配的子字符序列。当start=0时,该方法和lookingAt()的功能相同。
(5)public String replaceAll(String replacement):matcher调用该方法可以返回一个String对象,该String对象的字符序列是通过把s的字符序列中与模式regex匹配的子字符序列全部替换为参数replacement指定的字符序列得到的(注意s本身没有发生变化)。
(6)public String replaceFirst(String replacement):matcher调用该方法可以返回一个String对象,该String对象的字符序列是通过把s的字符序列中第1个与模式regex匹配的子字符序列全部替换为参数replacement指定的字符序列得到的(注意s本身没有发生变化)。
(7) public String group():返回一个String对象该对象的字符序列是find方法在s的字符序列中找到的匹配regex的子字符序列。

具体示例:

String regex="-?[0-9][0-9]*[.]?[0-9]*";//匹配数字,整数或浮点数的正则表达式
Pattern pattern=Pattern.compile(regex);//初始化模式对象
String s="市话费:28.39元,长途话费:49.15元,上网费:352元";
Matcher matcher=pattern.matcher(s);//初始化匹配对象,用于检索s
double sum=0;
while(matcher.find()){
String str=matcher.group();
sum+=Double.parseDouble(str);
System.out.println("从"+matcher.start()+"到"+matcher.end()+"匹配的子序列:");
System.out.println(str);
}
System.out.println("总费用:"+sum+"元");
String weatherForecast[]={"北京:-9度至7度","广州:10度至21度","哈尔滨:-29度至-7度"};//存放三地的温度
double averTemperture[]=new double[weatherForecast.length];//存放三地的平均温度
for(int i=0;i<weatherForecast.length;i++){
Matcher matcher1=pattern.matcher(weatherForecast[i]);//初始化匹配对象,模式不变
double sum1=0;
int count=0;
while(matcher1.find()){
count++;//一个地方有几个气温,count就加几次
sum1+=Double.parseDouble(matcher1.group()); //sum1表示的是一个地方最高气温与最低气温的和
}
averTemperture[i]=sum1/count;//for循环一次,算出一个地方的平均气温
}
System.out.println("三地的平均气温:"+Arrays.toString(averTemperture));
//输出结果为:
从4到9匹配的子序列:
28.39
从16到21匹配的子序列:
49.15
从27到30匹配的子序列:
352
总费用:429.53999999999996元
三地的平均气温:[-1.0, 15.5, -18.0]

到此这篇关于Java中字符序列的替换与分解的几种实现方法的文章就介绍到这了,更多相关Java中字符序列替换与分解内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java基于动态规划法实现求最长公共子序列及最长公共子字符串示例

    本文实例讲述了Java基于动态规划法实现求最长公共子序列及最长公共子字符串.分享给大家供大家参考,具体如下: 动态规划法 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题.简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加. 为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存于该数组中,这就是动态规划法所采用的基本方法. [问题] 求两字符序列的最长公共字符子序列 问题描述:字符

  • Java中字符序列的替换与分解的几种实现方法

    目录 一.使用String类 二.使用StringTokenizer类 三.使用Scanner类 四.使用Pattern类与Matcher类 一.使用String类 String对象调用public String replaceAll(String regex,String replacement)方法,返回一个新的String对象,返回的String对象的字符序列是把当前String对象的字符序列中,所有和参数regex相匹配的子字符序列替换成参数replacement指定的字符序列所得到的字

  • JAVA正则表达式及字符串的替换与分解相关知识总结

    JAVA正则表达式及字符串的替换与分解 Java 提供了 java.util.regex 包来与正则表达式进行模式匹配 java.util.regex 包主要包括以下三个类: Pattern 类: pattern 对象是一个正则表达式的编译表示.Pattern 类没有公共构造方法.要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象.该方法接受一个正则表达式作为它的第一个参数. Matcher 类: Matcher 对象是对输入字符串进行解释和匹配

  • 详解Java中字符流与字节流的区别

    本文为大家分析了Java中字符流与字节流的区别,供大家参考,具体内容如下 1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个"流动的方向",通常可以从中读入一个字节序列的对象被称为输入流:能够向其写入一个字节序列的对象被称为输出流. 2. 字节流 Java中的字节流处理的最基本单位为单个字节,它通常用来处理二进制数据.Java中最基本的两个字节流类是InputStream和Out

  • Java中字符编码格式详解

    一.前言 在分析Comparable和Comparator的时候,分析到了String类的compareTo方法,String底层是用char[]数组来存放元素,在比较的时候是比较的两个字符串的字符,字符用char来存储,此时,突然想到,Java里面的char可以存放中文吗?后来发现是可以的,并且由此也引出了Java中字符的编码格式问题. 二.Java存储格式 在Java中,如下代码获取了字符'张'的各种编码格式. import java.io.UnsupportedEncodingExcept

  • Java中字符数组、String类、StringBuffer三者之间相互转换

    一.StringBuffer与String的相互转换 1.将StringBuffer转换成String StringBuffer类成员toString函数可将其转换成String类型. StringBuffer buffer = newStringBuffer("abcd"); String str = buffer.toString(); 通过String类中的构造将一个StringBuffer类转换为String类:String(StringBuffer buffer) Strin

  • 基于java中byte数组与int类型的转换(两种方法)

    java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中,发送.者接收的数据都是 byte数组,但是int类型是4个byte组成的,如何把一个整形int转换成byte数组,同时如何把一个长度为4的byte数组转换为int类型.下面有两种方式. public static byte[] int2byte(int res) { byte[] targets = new byte[4]; targets[0] = (byte) (res & 0xf

  • java中hasNextInt判断后无限循环输出else项的解决方法

    话不多说,上来就是干! ?12345678910111213141516171819202122232425262728293031323334353637 import java.util.Scanner; public class Test_hasNextInt { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc = new

  • 浅谈Java中浮点型数据保留两位小数的四种方法

    目录 一.String类的方式 二.DecimalFormat类 三.BigDecimal类进行数据处理 四.NumberFormat类进行数据处理 总结一下 今天在进行开发的过程中遇到了一个小问题,是关于如何将double类型的数据保留两位小数.突然发现这方面有一点欠缺,就来总结一下. 一.String类的方式 该方式是是使用String的format()方法来实现的,该方法的作用就是规范数据的格式,第一个参数传入一个字符串来表示输出的数据格式,如保留两位小数就使用"%.2f",第二

  • java中List对象列表实现去重或取出及排序的方法

    前言 因为在面试的时候碰到几次list的去重和排序,觉着有必要给大家总结一下具体的方法,分享出来供大家学习参考,话不多说了,来一起看看下面介绍的一种做法: 一.list去重 1.1 实体类Student List<Student>容量10k以上,要求去重复.这里Student的重复标准是属性相同,因此需要重写equals和hashcode方法,不知道有几个可以手写出来. student的equals方法: public void equals(Object o){ if(this == o)

  • Java中防止数据重复提交超简单的6种方法

    目录 前言 模拟用户场景 前端拦截 后端拦截 1.基础版--HashMap 2.优化版--固定大小的数组 3.扩展版--双重检测锁(DCL) 4.完善版--LRUMap 5.最终版--封装 扩展知识--LRUMap 实现原理分析 总结 前言 有位朋友,某天突然问东哥:在 Java 中,防止重复提交最简单的方案是什么? 这句话中包含了两个关键信息,第一:防止重复提交:第二:最简单. 于是东哥问他,是单机环境还是分布式环境? 得到的反馈是单机环境,那就简单了,于是东哥就开始装*了. 话不多说,我们先

随机推荐