Home Tags Posts tagged with "字符串"

字符串

一、什么是JSON?

JSON:JavaScript Object Notation[JavaScript 对象表示法]

JSON 是存储和交换文本信息的语法。类似 XML。(什么是XML?XML 简介 – 什么是 XML? | 菜鸟教程 (runoob.com)

JSON采用完全独立于任何程序语言的文本格式,使JSON成为理想的数据交换语言


二、为什么需要JSON

https://zhuanlan.zhihu.com/p/33792109


三、JSON、JSON格式、JSON对象、JSON字符串是什么关系?(重点)

1.JSON

其实,JSON并不复杂,之所以新手会对JSON犯迷糊,原因是简称。(至少我是这个原因)无论是在工作中,还是在论坛上,绝大多数时候,我们把JSON对象和JSON字符串都简称为JSON,以至于你常常会听到这样的回答:

“这个响应你用JSON接收就行”

“你测试接口的时候要记得用JSON格式”

“把这个JSON解析一下”

久而久之,新手就把JSON格式、JSON字符串、JSON对象(又可分普通对象、JSON数组)三者搞混了,现在,我们就将它们的关系梳理清楚。

2.JSON格式

JSON格式是一种数据交互的格式

当客户端和服务端进行数据交互的时候(不仅是C/S模型,其他模型也可以使用JSON格式交互),需要定义数据格式,JSON格式就是其中一种。

JSON格式是从JavaScript演变而来的

JSON是从 JavaScript 脚本语言中演变而来,使用Javascript语法来描述数据对象,文件名扩展是 .json,但是JSON格式仅仅是一个文本,仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态(PHP,JSP,.NET)编程语言都支持JSON

JavaScript对象的定义语法如下:

var person = {firstName:"Bill",
              lastName:"Gates", 
              age:62, 
              eyeColor:"blue"};
而JSON格式则长这样:
{
    "book": [
        {
            "id":"01",
            "language": "Java",
            "edition": "third",
            "author": "Herbert Schildt"
        },
        {
            "id":"07",
            "language": "C++",
            "edition": "second"
            "author": "E.Balagurusamy"
    }]
}

 JSON格式和JavaScript的区别

 二者之间的详细总结可以参考下述文章:JavaScript JSON的总结 – 知乎 (zhihu.com)

3.JSON字符串

首先,请清晰一点,JSON字符串本质上就是字符串。

String url = “https://restapi.amap.com/v3/config/district?output=JSON&key=75bf29a927a4ce42358665b507493393&extensions=base” + “&” + “keywords=” + keywords;
String result = HttpUtil.get(url);
上述代码是高德查询省市区的接口,返回值如下:诺,我们一眼就能发现,这不就是JSON格式的数据吗,我们直接用字符串类型的result去接收,一点问题都没有。
其实用什么类型去接收返回值,是由方法决定的
如果方法返回的是一个JSONObject类型,那你直接使用JSONObject去接收
如果方法返回的是一个JSON格式的字符串,那你直接使用String去接收,然后再把这个String类型转换成JSONObject类型或者JSONArray即可
那么,我们为什么要把String类型转成JSONObject或者JSONArray呢?

4.JSON对象(JSONObject、JSONArray)

为什么要把String类型转成转成JSONObject或者JSONArray,其实是业务决定的。你想想,如果我们需要通过高德接口查询某一个省下面的市信息,那么如果返回值是String类型的话,我们单单想获取市名称列表,即List<name>,需要对字符串进行截断,拼接等等一系列的麻烦操作,这个过程还极其容易出错。所以,我们直接使用JSONObject类型,其本质是k-v结构


四、JSON字符串和JSONObject对象的相互转换

我们可以使用FastJson 的JSONObject.parseObject(jsonStr)将JSON字符串转换为JSONObject对象,之后可以直接通过get(key)获取对应的属性值

JSONObject parse = JSONObject.parseObject(result);
//通过key取JSONArray
JSONArray puisneList = parse.getJSONArray("districts");
//通过key取JSONObject
JSONObject name = parse.get("jsonObject");
//通过key取属性值
String name = parse.get("name");

四、JSON字符串和Java对象的相互转换

JSON字符串转Java对象:JSON.parseObject(jsonStr, Target.class)

Java对象转JSON字符串:JSON.toJSONString(TargetObject)


五、JSONObject和Java对象的相互转换

Java对象—>JSON对象

Student stu = new Student(“公众号BiggerBoy”, “m”, 2);
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(stu);

JSON对象—>Java对象

Student stu = new Student(“公众号BiggerBoy”, “m”, 2);
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(stu);
Student student = JSONObject.toJavaObject(jsonObject, Student.class);

JSON字符串—>Java对象

ReportExceptionDto frontReportExceptionDto = JSONObject.parseObject(jsonObject.toJSONString(), ReportExceptionDto.class);

注意区别:toJavaObject和parseObject两个方法都可以将jsonObject转换为Java对象,
但是toJavaObjec没有处理json转换对象$ref关键词,而parseObject方法处理了!

toJavaObject和parseObject,区别是:

parseObject的第一个参数是json字符串;

toJavaObject的第一个参数是json对象;

参照:JSONObject.toJavaObject的使用以及其他方法的使用JSON与Java对象的转换_sucsmanw的博客-CSDN博客_jsonobject to object
      Fastjson-JSON.toJavaObject(String text, Class<T>)与JSONObject.toJavaObject(JSON json, Class<T> clazz)_hanjq_code的博客-CSDN博客_fastjson tojavaobject


五、JSON字符串和JavaScript对象的相互转换

JSON和JS对象的相互转换 (biancheng.net)

 JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,所以 JSON 本质是一个字符串。通过 JSON 调用相应的方法,JSON 和 JS 对象可以相互转换。

将JSON字符串转换为JS对象

通过 JSON字符串的 parse() 方法,可以将一个 JSON字符串 解析为一个JS对象,解析格式如下:JSON.parse(json)【JSON —> JS对象】

例如:

var json = '{"name":"张三", "age":36}';//定义一个JSON
var obj = JSON.parse(json);//调用parse()将json解析为一个JS对象
console.log(obj);//输出:{name: "张三", age: 36}

将JS对象转换为JSON字符串

通过 JSON 的 stringify() 方法,可以将一个 JS 对象转换为 JSON,转换格式如下:JSON.stringify(obj)【JS对象—>JSON字符串】

例如:

var obj = {name:"张三", age:36};//定义一个JS对象
var json = JSON.stringify(obj);//调用stringify()将一个JS对象转换为JSON
console.log(json);//输出:{"name":"张三","age":36}

Integer.parseInt(s)与Integer.valueOf(s)的区别详解

一、Integer.parseInt(s)用法

        String s1 = "1000";
        String s2 = "1000";
        int n1 = Integer.parseInt(s1);
        int n2 = Integer.parseInt(s2);
        if (n1 == n2) {         System.out.println("Integer.parseInt(s1) == Integer.parseInt(s2)");
        }

输出:

Integer.parseInt(s1) == Integer.parseInt(s2)
  • 1

Integer.parseInt(s)的作用就是把字符串s解析成有符号的int基本类型。

二、Integer.valueOf(s)用法

        String s = "123";
        Integer integer = Integer.valueOf(s);
        System.out.println("integer : " + integer);
  • 1
  • 2
  • 3

Integer.valueOf(s)把字符串s解析成Integer对象类型,返回的integer 可以调用对象中的方法。

三、Integer.parseInt(s)与Integer.valueOf(s)的区别

Integer.parseInt(s) 
Integer.parseInt(s)多次解析同一个字符串得到的int基本类型数据是相等的,可以直接通过“==”进行判断是否相等

        String s = "10000";
        if (Integer.parseInt(s) == Integer.parseInt(s)) { //true
            System.out.println("Integer.parseInt(s) == Integer.parseInt(s)");
        }
  • 1
  • 2
  • 3
  • 4

输出:

Integer.parseInt(s) == Integer.parseInt(s)
  • 1

int是基本类型,不含有equals方法,所以只能用“==”比较,基本类型用“==”比较的是两个值的大小。

Integer.valueOf(s)
Integer.valueOf(s)多次解析相同的一个字符串时,得到的是Integer类型的对象,得到的对象有时是同一个对象,有时是不同的对象,要根据把s字符串解析的整数值的大小进行决定:如果s字符串对应的整数值在 -128~127之间,则解析出的Integer类型的对象是同一个对象;如果s字符串对应的整数值不在-128~127之间,则解析出的Integer类型的对象不是同一个对象。不管对象是否相等,对象中的value值是相等的。

        String s = "100";
        Integer i1 = Integer.valueOf(s);
        Integer i2 = Integer.valueOf(s);
        if (i1 == i2) { //两个对象相等
            System.out.println("i1 == i2");
        }
        if (i1.equals(i2)) { //两个对象中的value值相等
            System.out.println("i1.equals(i2)");
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

输出:

i1 == i2
i1.equals(i2)
  • 1
  • 2

通过上面示例,字符串s对应的整数值为100,在-128~127之间,所以解析出的两个对象i1和i2是相等的。equals是比较的两个对象i1和i2中的value值是否相等,“==”是比较i1和i2两个对象是否相等。

当s字符串对应的整数值不在-128~127之间,示例如下:

        String s = "1000";
        Integer i1 = Integer.valueOf(s);
        Integer i2 = Integer.valueOf(s);
        if (i1 != i2) { //两个对象不相等
            System.out.println("i1 != i2");
        }
        if (i1.equals(i2)) { //两个对象中的value值相等
            System.out.println("i1.equals(i2)");
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

输出:

i1 != i2
i1.equals(i2)
  • 1
  • 2

可见,当s字符串对应的整数值为1000,不在-128~127之间,通过Integer.valueOf(s)解析出的两个对象i1和i2是不同的对象,对象中的value值是相同的。

原因: 为什么Integer.valueOf(s)会出现这种情况呢?这是由于JDK中源码已经定义好的。由于在-128~127之间的整数值用的比较频繁,当每次要创建一个value值在-128~127之间的Integer对象时,直接从缓存中拿到这个对象,所以value值相同的Integer对象都是对应缓存中同一个对象。-128~127之外的整数值用的不是太频繁,每次创建value值相同的Integer对象时,都是重新创建一个对象,所以创建的对象不是同一个对象。这个从JDK中源码可以看出

    public static Integer valueOf(String s) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, 10));
    }
  • 1
  • 2
  • 3

然后上面的源码又调用了Integer.valueOf(int)方法

    public static Integer valueOf(int i) {
        /*IntegerCache.low为 -128;
        IntegerCache.high默认为127,但可以在JVM进行配置,一般默认就是127*/
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            /*如果i在-128~127之间,从缓存中取对象*/
            return IntegerCache.cache[i + (-IntegerCache.low)];
        /*如果i不在-128~127之间,重新创建一个对象*/
        return new Integer(i);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

四、Integer.parseInt(s)与Integer.valueOf(s)的联系

Integer.parseInt(s)是把字符串解析成int基本类型,Integer.valueOf(s)是把字符串解析成Integer对象类型,其实int就是Integer解包装,Integer就是int的包装,在jdk8中已经自动实现了自动解包装和自动包装,所以两种方式都能得到想要的整数值。

把int类型包装成Integer类型

        Integer i = 1000;  //自动把1000类型包装成Integer类型
        Integer i2 = 1000;
        if (i != i2) {
            System.out.println("i != i2");
        }
        if (i.equals(i2)) {
            System.out.println("i.equals(i2)");
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出:

i != i2
i.equals(i2)
  • 1
  • 2

把Integer类型自动解包装成int类型

        Integer n = new Integer(100);
        int n1 = n;
        System.out.println("n1 = " + n1);
  • 1
  • 2
  • 3

输出:

i.equals(i2)
n1 = 100

String、StringBuffer和StringBuilder的区别

String

String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。

这个是String类的解释,之前小咸儿看到这个情况,不能理解上述的解释,如下

String a = "123";
a = "456";
// 打印出来的a为456
System.out.println(a)
  • 1
  • 2
  • 3
  • 4

看到这里,小咸儿不明白了,这不是明明已经对他进行修改了吗?为什么还说他是一个不可变类呢?

经过小咸儿和小伙伴们的学习,明白String类不可变在哪里体现出来的,接下来就看一张上述a对象的内存存储空间图
在这里插入图片描述

可以看出来,再次给a赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“456”这个字符串,a则指向最新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。

StringBuffer

StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。

StringBuffer b = new StringBuffer("123");
b.append("456");
// b打印结果为:123456
System.out.println(b);
  • 1
  • 2
  • 3
  • 4

在看一下b对象的内存空间图:
在这里插入图片描述

所以说StringBuffer对象是一个字符序列可变的字符串,它没有重新生成一个对象,而且在原来的对象中可以连接新的字符串。

StringBuilder

StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。

StringBuffer是如何实现线程安全的呢?

StringBuffer类中实现的方法:

在这里插入图片描述

StringBuilder类中实现的方法:

在这里插入图片描述

由此可见,StringBuffer类中的方法都添加了synchronized关键字,也就是给这个方法添加了一个锁,用来保证线程安全。

Java9的改进

Java9改进了字符串(包括String、StringBuffer、StringBuilder)的实现。在Java9以前字符串采用char[]数组来保存字符,因此字符串的每个字符占2字节;而Java9的字符串采用byte[]数组再加一个encoding-flag字段来保存字符,因此字符串的每个字符只占1字节。所以Java9的字符串更加节省空间,字符串的功能方法也没有受到影响。

  1. 可以通过ArrayList<String> str2 = new ArrayList<String> ()方式创建字符串数组,如下图所示:
  2. java怎么创建字符串数组
    1. 第一步通过String s = String.valueOf(a);方式,将数字a转换成字符串s,如下图所示:

      java中怎么将数字转换成字符串
    2. 第二步运行程序之后,可以看到已经成功将数字转换成字符串了,如下图所示:

      java中怎么将数字转换成字符串
    3. 第三步通过String s2 = Integer.toString(a);方式,将数字a转换成字符串s2,如下图所示:

      java中怎么将数字转换成字符串
    4. 第四步运行java程序,可以看到转换成功了,如下图所示:

      java中怎么将数字转换成字符串
    5. 第五步也可以通过加双引号的方式,将数字转换成字符串,如下图所示:

      java中怎么将数字转换成字符串

indexOf方法可以用来检查一个串是否是另一个串的子串。
jdk中的表述如下
indexOf
public int indexOf(String str)返回指定子字符串在此字符串中第一次出现处的索引。返回的整数是
this.startsWith(str, k)
为 true 的最小 k 值。

参数:
str – 任意字符串。
返回:
如果字符串参数作为一个子字符串在此对象中出现,则返回第一个这种子字符串的第一个字符的索引;如果它不作为一个子字符串出现,则返回 -1。

依据描述可利用该方法实现判断一个字符串是否在另外一个字符串中。
索引都是从0开始的,如果出现字符串不包含另一个字符串则返回-1.

如下demo方便理解。

package test;

public class Test {
public static void main(String[] args) {
String x = “Hello World/XXX”;
String y = “Hello World/”;
System.out.println(“返回 y 在x 中第一次出现处的索引值为:”+x.indexOf(y));
System.out.println(“返回 x 在y 中第一次出现处的索引值为:”+y.indexOf(x));
if(x.indexOf(y)!=-1){
System.out.println(“x包含y”);
}else{
System.out.println(“x不包含y”);
}
}
}

运行结果:
返回 y 在x 中第一次出现处的索引值为:0
返回 x 在y 中第一次出现处的索引值为:-1
x包含y

1.C 库函数 – isalpha()

C 标准库 - <ctype.h> C 标准库 – <ctype.h>

描述

C 库函数 void isalpha(int c) 检查所传的字符是否是字母。


2.判断字符是否为数字的函数–int isdigit( int ch )

用于判断字符是否为字母的函数–int isdigit( int ch )。

【包含的头文件】需要引入的头文件:#include <ctype.h>

【功能】如果参数是0到9之间的数字字符,函数返回非零值,否则返回零值;

  1. char c;
  2.  
    scanf( “%c”, &c );
  3.  
    if( isdigit(c) )
  4.  
    printf( “You entered the digit %c\n”, c );
其他详情见:
https://www.runoob.com/cprogramming/c-standard-library-ctype-h.html;

给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。
示例 1:
输入:”ab-cd”
输出:”dc-ba”
示例 2:
输入:”a-bC-dEf-ghIj”
输出:”j-Ih-gfE-dCba”
示例 3:
输入:”Test1ng-Leet=code-Q!”
输出:”Qedo1ct-eeLg=ntse-T!”
char * reverseOnlyLetters(char * S){
    //可以用isalpha函数宏定义(islower小写isupper大写)判断是否为字母;
    int i=0,j=strlen(S)-1;//双指针,一个头一个尾;
    if(j<=0)return S;
    while(i<=j){
        if(isalpha(S[i])&&isalpha(S[j])){//双指针所指向都是字母;
            char temp=S[i];
            S[i++]=S[j];
            S[j–]=temp;
        }//交换,并且指针同时移动;
        //其他留在原地就好了;
        if(!isalpha(S[i])){
            i++;
        }//移动前指针;
        if(!isalpha(S[j])){
            j–;
        }
    }
    return S;
}
宏定义和函数:
不同。虽然功能近似,但bai函数会产生独立代码,每du次调用执行的zhi是同一个位置的代码,无论调用多少次dao。宏定义是简单的文本替换,产生的代码是替换后程序产生的代码,简单说就是程序里每次使用宏替换后的地方都要产生类似的代码,而这些替换后产生的代码存在于程序的不同位置。宏定义不检查参数类型,仅仅是简单的文本替换

给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。
题目数据保证线路图会形成一条不存在循环的线路,因此只会有一个旅行终点站。
示例 1:
输入:paths = [[“London”,”New York”],[“New York”,”Lima”],[“Lima”,”Sao Paulo”]]
输出:”Sao Paulo”
解释:从 “London” 出发,最后抵达终点站 “Sao Paulo” 。本次旅行的路线是 “London” -> “New York” -> “Lima” -> “Sao Paulo” 。
解题思路:比较两个字符串使用strcmp函数
char *destCity(char ***paths, int pathsSize, int *pathsColSize)
{
    int i, j;
    int flag;            // 是否终点城市标记
    for (i = 0; i < pathsSize; i++) {
        flag = 0;
        for (j = 0; j < pathsSize; j++) {
            if (strcmp(paths[i][1],paths[j][0])==0) {/*字符串比较要用strcmp函数,而不能使用path[i][1]==paths[j][0];
            因为字符串二维数组是如下定义:
            char c[3][8]={“apple”,”orange”,”banana”}
            等价于char c[3][8]={{“apple”},{“orange”},{“banana”}};
            3表示行,每一行只有一个字符串;
            8表示列,也就是每个字符串的最大长度;
            详情见:  http://c.biancheng.net/view/273.html
            */
                flag = 1; // 标记为1,表示在起点城市中可以找到
            }
        }
        if (flag == 0) {
            return paths[i][1];
        }
    }
    
    // 返回NULL,该句很重要,不然编译有误:control reaches end of non-void function
    return NULL;
}