1,基本介绍
介绍两个API: String类和ArrayList类
API(全称Application Programming Interface:应用程序编程接口)
就是别人写好的一些程序,给程序员直接拿去调用即可解决问题的代码类。
什么是包?
包是用来分门别类的管理各种不同程序的,类似于文件夹,建包有利于程序的管理和维护。
在自己程序中调用其他包下的程序的注意事项
-
如果当前程序中,要调用自己所在包下的其他程序,可以直接调用。(同一个包下的类,互相可以直接调用)
-
如果当前程序中,要调用其他包下的程序,则必须在当前程序中导包, 才可以访问!
导包格式:import 包名.类名;
-
如果当前程序中,要调用Java提供的程序,也需要先导包才可以使用;但是Java.lang包下的程序是不需要我们导包的,可以直接使用。
-
如果当前程序中,要调用多个不同包下的程序,而这些程序名正好一样,此时默认只能导入一个程序,另一个程序必须带包名访问。
2,String类
String是java提前写好的一个类,存放在java.lang包下,代表着所有的字符串对象,可以用来封装字符串类型的数据,并提供了很多操作字符串的方法,程序员只需要面向字符串对象,调用这些提前写好的方法,就可以完成很多字符串相关的操作了;
String类的使用步骤:
-
想方设法得到一个字符串对象;(用双引号,键盘输入,String的构造方法等各种手段均可)
-
面向字符串对象调用String类中的方法;
-
处理方法产出的结果;
String创建对象封装字符串数据的两种方式:
方式一: Java 程序中的所有字符串文字(例如“abc”)都为此类的对象。
String name = "宗介";
String schoolName = "早稻田";
方式二: 调用String类的构造器初始化字符串对象。 一般不使用构造器,太浪费内存,后面会分析
构造器 | 说明 |
---|---|
public String() | 创建一个空白字符串对象,不含有任何内容 |
public String(String original) | 根据传入的字符串内容,来创建字符串对象 |
public String(char[] chars) | 根据字符数组的内容,来创建字符串对象 |
public String(byte[] bytes) | 根据字节数组的内容,来创建字符串对象 |
String str = "hello";
String hello = new String();
String hello = new String("hello");
System.out.println(hello);
char[] arr = {'a','b','c'};
String s = new String(arr);
System.out.println(s);
byte[] bytes = {97,98,99};
String s1 = new String(bytes);
System.out.println(s1);
String提供的操作字符串数据的常用方法: 这些都是最最最常用的一定牢记
方法名 | 说明 |
---|---|
public int length() | 获取字符串的长度返回(就是字符个数) |
public char charAt(int index) | 获取某个索引位置处的字符返回 |
public char[] toCharArray(): | 将当前字符串转换成字符数组返回 |
public boolean equals(Object anObject) | 判断当前字符串与另一个字符串的内容一样,一样返回true |
public boolean equalsIgnoreCase(String anotherString) | 判断当前字符串与另一个字符串的内容是否一样(忽略大小写) |
public String substring(int beginIndex, int endIndex) | 根据开始和结束索引进行截取,得到新的字符串(包前不包后) |
public String substring(int beginIndex) | 从传入的索引处截取,截取到末尾,得到新的字符串返回 |
public String replace(CharSequence target, CharSequence replacement) | 使用新值,将字符串中的旧值替换,得到新的字符串 |
public boolean contains(CharSequence s) | 判断字符串中是否包含了某个字符串 |
public boolean startsWith(String prefix) | 判断字符串是否以某个字符串内容开头,开头返回true,反之 |
public String[] split(String regex) | 把字符串按照某个字符串内容分割,并返回字符串数组回来 |
public int compareTo(String anotherString) | 按字典顺序比较两个字符串。 |
对于split方法需要特殊的注意: 通过代码展示
// 需求: 想让字符串以 '.' 为切分点进行切分
String str = "1.2.3";
String[] split = str.split(".");
System.out.println(split.length); // 0 这里是0
但是结果却是0 ,为什么?
首先需要了解 正则表达式中的特殊字符:正则表达式中有 15 个元字符,是有特殊意义的,使用时需要转义,这 15 个字符分别是:
( [ { \ ^ - $ ** } ] ) ? * + .
因为“.” 是特殊字符, 且split是支持正则表达式的,所以正确表示应该是“\\.”
首先介绍一下: ‘.’ 在正则中的意思是 : 匹配除换行符 \n 之外的任何单字符
所以结果为 0 也就解释的通了: 因为这里str.split("."), 是以任何一个字符作为分割,分割完就没了 为0
那么如果想用应该怎么办呢? 转义,告诉java这不是一个特殊字符 通过 \ , 但是会发现 \ 也是一个特殊字符,那么就需要先对\ 进行转义, 即 : \\. 就可以代表普通字符的 ‘.’ , 即代码如下:
String str = "1.2.3";
String[] split1 = str.split("\\.");
System.out.println(split1.length); // 3
另外除了split()还有replace , replaceAll ,这两者都是由正则表达式类库实现的,但是 replace 采用的是字符串原有的意思来替换,而 replaceAll 则是按照正则表达式的字符串来替换
另外对于split()方法还有一个注意的点 , 就是含头不含尾: 示例如下;
String str = "abbaccadda";
String[] as = str.split("a");
for (String a : as) {
System.out.println(a);
}
结果如下: 切割之后如果前面没有就会保留空行,但是如果后面没有就不在保留. 即 含头不含尾
// 这里是头
bb
cc
dd
String使用时的注意事项:
第一点:
String对象的内容不可改变,被称为不可变字符串对象。
第二点:
只要是以 “ ” 方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只存储一份;
但通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中。
String注意事项1: String的对象是不可变字符串对象 示例如下:
内存示意图: 注意常量池和堆的变化 这个图貌似有一点问题,就是常量池在方法区中
那么问题又来了,堆中的数据是什么时候new出来的?
现在把目光定睛在常量池中,会发现通过 “ ” 定义的常量都在常量池中,这样的好处是调用同样的名字的时候都指向常量池中的同一个地址,大大的节省了内存。但是如果是两个字符串相加的话,java会自动拼接,设想如果常量池中没有拼接后的就会重新创建,开辟空间,之前存储的也就成为了垃圾,很麻烦且很浪费,所以在后面java内部就是用StringBuilder对象的append完成拼接。API中的具体描述如下:
Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。有关字符串串联和转换的更多信息,请参阅 Gosling、Joy 和 Steele 合著的 The Java Language Specification。
public static void main(String[] args) {
String s1 = "我爱";
String s2 = "java";
String s3 = s1 + "," + s2;
// 其实 java内部处理是这样子做的
// String s3 = (new StringBuilder().append(s1).append(",").append(s2).toString());
}
当知道了java内部的处理变量的机制,那么再看下下面的结果:
首先我们知道 == 号对于引用类型比较的是其内存地址,第一个为false我们就很明白,因为在拼接的时候创建了StringBuilder对象使用其append()方法完成的拼接;因为new了所以两者的内存地址肯定不一样,一个在常量池中,一个在堆的普通区中。那么第二个为什么是true呢?
因为Java存在编译优化机制,程序在编译时: “a” + “b” + “c” 会直接转成 abc,以提高程序的执行性能。即如果是常量(字面量拼接的时候,java会做出一些优化,来提高性能.)
这样就显而易见了.
继续来看String类:
public static void main(String[] args) {
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1 == str2); //
}
第二行和第三行创建了几个对象:
很明显第二行在堆中的常量池中创建了对象, 第三行,因为堆中有了一模一样的数据,所以就不在在常量池中创建,但是因为new了一个实例,所以在堆中还是会创建一个对象,所以第二行第三行分别创建了一个对象; 又因为两个的指向不同str1指向常量池,str2指向堆中的地址所以肯定不同啦,false;
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = "abc";
System.out.println(str1 == str2);
}
这个第二行和第三行创建了几个对象: 分别是两个和零个
首先常量池中一个,其次在在堆中一个,所以两个
第三行,因为常量池中有了相同的常量(字面量), 所以就不在创建直接引用。这也体现了常量池的好处
3,ArrayList类
集合是一种容器,用来装数据的,类似于数组。但集合类是强调通过对象来实现对数据的处理,并且不限制长度会自动的扩容 ,大小可变。
首先介绍一种形式:
ArrayList
在java中称为泛型: 后面的笔记会提到,在这里我们只需要知道,如果集合中想存什么类型的数据,那么就把
构造器:
构造器 | 说明 |
---|---|
public ArrayList() | 构造一个初始容量为 10 的空列表。 |
ArrayList(int initialCapacity) | 构造一个具有指定初始容量的空列表。 |
常用方法:
常用方法名 | 说明 |
---|---|
public boolean add(E e) | 将指定的元素添加到此集合的末尾 |
public void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合中的元素的个数 |
public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 |
public E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
代码示例:
public static void main(String[] args) {
ArrayList<String> stringList = new ArrayList<>();
// add(E e)
stringList.add("芝诺的乌龟");
stringList.add("拉普拉斯兽");
// add(int index,E element) 通过索引插入到已有的元素中,索引最大为stringList.size();
stringList.add(2, "麦克斯韦妖");
stringList.add(2, "薛定谔的猫");
// size()获取集合的长度
int size = stringList.size();
System.out.println("集合的长度为:" + size);
// get(int index) 通过索引获取值
String str = stringList.get(2);
System.out.println("2 索引的值为:" + str);
// set(int index,E element) 修改指定索引处的元素,返回被修改的元素
String str2 = stringList.set(2, "尼古拉斯的狗");
System.out.println("2 处的位置修改之前为:" + str2);
// 删除
// remove(int index) 删除指定索引处的元素,返回被删除的元素
String str3 = stringList.remove(2);
System.out.println("索引为2的" + str3 + "被删除了");
// remove(Object o) 删除指定的元素,返回删除是否成功
String name = "芝诺的乌龟"; // String对象
boolean remove = stringList.remove(name);
System.out.println(name + "是否删除:" + remove);
}
输出结果:
集合的长度为:4
2 索引的值为:薛定谔的猫
2 处的位置修改之前为:薛定谔的猫
索引为2的尼古拉斯的狗被删除了
芝诺的乌龟是否删除:true
最后一个需要特别注意的问题:
在删除的时候,当前一个数据被删除的时候,那么后面的数据会自动的向前补位,代码示例如下:
public static void main(String[] args) {
// 需求: 删除包含java的所有数据
// 包含,应该想到contains()方法 .删除就是remove() 所有那么就需要遍历了
ArrayList<String> list = new ArrayList<>();
// 添加数据
list.add("java从入门到精通");
list.add("javaWEB基础");
list.add("mysql从删库到跑路");
list.add("java语言程序设计");
for (int i = 0; i < list.size(); i++) {
// 如果包含就删除
if (list.get(i).contains("java")){
list.remove(i);
}
}
for (String str : list) {
System.out.println(str);
}
}
不看结果设想一下控制台应该输出什么:
javaWEB基础
mysql从删库到跑路
上面的结果就是因为有两个和java相关的内容紧挨着, 在删除的时候当 前一个被删除了,后一个就不填补空位, 但是这时的 变量i 会自增,从而错过.
找到了问题 , 下面就解决问题.不让 当前一个删除的时候不让 i 自增. 修改后for循环如下:
for (int i = 0; i < list.size(); i++) {
// 如果包含就删除
if (list.get(i).contains("java")){
list.remove(i);
// 和++ 抵消,相当于不动
i--;
}
}
上面是从索引下手的: 那么我们也可以从原因下手,原因是因为 集合的自动填补空位. 那么我们从后面遍历判断就不会有这种情况了. 循环删除部分代码示例如下:
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i).contains("java")){
list.remove(i);
}
}
结果如下:
mysql从删库到跑路
标签:day08,java,String,int,ArrayList,list,字符串,public From: https://www.cnblogs.com/yfs1024/p/17134445.html2.19 祸不单行的一天依然要加油呀