目录
拆分练习:将"张三.23|李四.24|王五.25"转为学生类信息
(2)StringBuilder、StringBuffer的API
(1)Collection接口是Collection系列集合的根接口
String类的常用方法
【系列1:常用方法】
boolean isEmpty()
字符串是否为空
int length()
返回字符串的长度
String concat()
拼接,等价于“+”
boolean equals(Object obj)
比较字符串是否相等,区分大小写
boolean equalsIgnoreCase(Object obj)
比较字符串是否相等,不区分大小写
int compareTo(String other)
比较字符串大小,区分大小写,按照Unicode编码值比较大小
int compareToIgnoreCase(String other)
比较字符串大小,不区分大小写
String toLowerCase()
将字符串中大写字母转为小写
String toUpperCase()
将字符串中小写字母转为大写
【注意】这里不是直接使用str.toUpperCase
而是要用一个新对象去接收String newString = str.toUpperCase;
String trim()
去掉字符前后空白符
public String intern()
结果在常量池中共享
String str = "hello";
String newString = str.trim();
str == newString; 返回true
hello的前后没有空格,trim()没有做任何修改
在源码中,如果没变化,return this
String str = "hello ";
String newString = str.trim();
str == newString; 返回false
【系列2:查找】
boolean contains(xx):是否包含xx
int indexOf(xx):从前往后找当前字符串xx,如果有,返回第一次出现的下标,如果没有,返回-1
int lastIndexOf(xx):从后往前找字符串xx,如果有,返回第一次出现的下标,如果没有,返回-1
【系列3:字符串截取】
String substring(int beginIndex):
返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串
String substring(int beginIndex,int endIndex):
返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串
【系列4:和字符或字符数组相关】
char charAt(index):返回[index]位置的字符
char[] toCharArray():将此字符串转换为一个新的字符数组返回
String(char[] value):返回指定数组中表示该字符序列的String
String(char[] value,int offset,int count):返回指定数组中表示该字符序列的String
static String copyValueOf(char[] data):返回指定数组中表示该字符序列的String
static String copyValueOf(char[] data,int offset,int count):
返回指定数组中表示该字符序列的String
static String valueOf(char[] data,int offset,int count):返回指定数组中表示该字符序列的String
static String valueOf(char[] data):返回指定数组中表示该字符序列的String
【系列5:编码与解码(和字节相关)】
①编码:把字符串转为字节数组
②解码:把字节数组翻译为字符串
当字符串不仅仅是在内存中使用时,需要把它写到文件,或者发送到网络中,这个时候就要把字符串转为字节数组处理
byte[] getBytes():编码,把字符串变为字节数组,按照平台默认的字符编码进行解码
byte[] getBytes(字符编码方式):按照指定编码方式进行编码
new String(byte[])或new String(byte[],int,int):解码,按照平台默认的字符编码进行解码
new String(byte[],字符编码方式)或new String(byte[],int,int,字符编码方式):解码,按照指定的编码方式进行解码
【系列6:开头和结尾】
boolean startsWith(xx):是否以xx开头
boolean endsWith(xx):是否以xx结尾
判断是不是Java的源文件,依据就是后缀名是不是.java文件
fileName.endsWith(".java")
【系列7:正则匹配】
boolean matchs(正则表达式):判断当前字符串是否匹配某个正则表达式
【系列8:替换】
String repalce(xx,xx) 不支持正则
String replaceFirst(正则,value) 替换第一个匹配部分
String repalceAll(正则,value) 替换所有匹配部分
如:敏感词替换
String str = "我要口吐芬芳啦!";
str = str.replace("口吐芬芳","***");
输出:我要***啦!
将非字母字符去掉
String str = "hello1234world$$";
str = str.replaceAll("^[a-zA-Z]+",""); 表示一位或多位是加法
输出helloworld
【系列9:拆分】
String[] split(正则):按照某种规律进行拆分
String str = "hello a new world of java";
String[] strings = str.split(" ");
按照空格进行拆分,存入字符串数组中
如果单词之间有多个空格的话
String[] strings = str.split(" +");
String str = "1hello2java3world";
String[] strings = str.split("\\d");
意为按照数字进行拆分,但是此时会将1前面以为是一个空字符串
故进行优化:
String str = "1hello2java3world";
str = str.replaceFirst("^\\d"); 去掉第一个开头的数字
String[] strings = str.split("\\d");
拆分练习:将"张三.23|李四.24|王五.25"转为学生类信息
public class Student{
private String name;
private int age;
public Student(String name,int age){
this.name = name;
this.age = age;
}
}
public class Test{
public static void main(String[] args){
String str = "张三.23|李四.24|王五.25";
String[] studentString = str.split("\\|"); //在正则中|表示或,注意转义
for(String studentInfo : studentString){
String[] strings = studentInfo.split("\\.");
Student student = new Student(strings[0],Integer.parseInt(strings[1]));
}
}
}
【可变字符序列】
(1)String与可变字符序列的区别
因为String对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低(一直有新对象产生)。因此,JDK在java.lang包提供了可变字符序列StringBuilder和StringBuffer类型——字符串缓冲类
StringBuffer:老的,线程安全的(因为有synchronized修饰)
StringBuilder:线程不安全的
因为大多时候,StringBuffer和StringBuilder的对象都是被单个线程使用,而不是多线程
单线程不需要考虑安全问题,就没必要加同步锁,加了反而影响性能
(2)StringBuilder、StringBuffer的API
常用的API、StringBuilder、StringBuffer的API是完全一致的
构造器:
StringBuffer和StringBuilder不能直接用""赋值,必须new对象,因为""只能是String类型
它们三个之间没有父子类关系,所以不能直接类型转换
StringBuilder str = "hello"; 错误,类型不兼容
StringBuilder str = new StringBuilder("hello"); 正确
(1) StringBuilder append(xx):在最后拼接、追加
StringBuilder str = new StringBuiler("hello");
str.append("java"); 直接拼接,不建新对象
str.appenf("world");
System.out.println(str); 输出hellojavaworld
由于修改字符串的方法,返回值类型仍是StringBuilder,那么意味着可以“连写”,即将上面的代码修改为:
str.append("java").appenf("world");
(2) StringBuilder insert(int index,xx):在[index]位置插入xx
(3) StringBuilder delete(int start,int end):删除[start,end]之间字符
StringBuilder deleteCharAt(int index):删除[index]位置字符
(4) void setCharAt(int index,xx):替换[index]位置字符
(5) StringBuilder reverse():反转
(6) void setLength(int newLength):设置当前字符序列长度为newLength
(7) StringBuilder replace(int start,int end,String str):替换[start,end)范围的字符序列为str
(8) int indexOf(String str):在当前字符序列中查询str第一次出现的下标
(3)为什么可变
①char[ ] value没有final修饰
②所有修改的方法,是直接在value数组上进行修改的,如果涉及到扩容,也会让value指向新数组
【集合】
1. 什么是集合?
集合是一种容器,或也可以叫做一种数据结构
这里讲容器部分
2. 集合和数组的区别与联系
联系:首先它们都是容器,其次很多集合底层也是数组,很多集合都是对容器的再此封装
区别:
数组:(1)可以装基本数据类型的数据,也可以装对象
(2)数组大小是确定的,除非手动扩容、复制,即原有数组不可更改大小
(3)数组元素时连续存储,在内存中会开辟一整块连续存储空间,那么其访问速度是很高的,可以根据数组下标直接定位到某个元素
(4)数组结构比较单一
集合:(1)只能装对象,当基本数据类型存入,会自动装箱为对象
(2)集合对使用者来说,可以自动扩容,不用使用者去做任何额外的操作
(3)集合元素有的是连续存储,有的不是(数组或链表或树),返回效率不一定高
(4)集合种类非常多,有ArrayList、HashSet、TreeSet等
3. 集合分类
两大类,Collection和Map
Collection:存储一组对象,一个一个对象凑出一组,比喻单身party
Map:存储一对一对的键值对(映射关系),比喻情侣party(key是一个对象,value也是一个对象)或家庭party(key是一个对象,value是一个集合)
4. Collection系列的集合
(1)Collection接口是Collection系列集合的根接口
Collection表示一组对象,这些对象也称为Collection的元素。一些collection允许有重复的元素,而另一些则不允许。一些collection是有序的,而另一些是无序的
JDK不提供此接口的任何直接实现:它提供更具体的子接口(如Set和List、Queue等子接口)实现
Collection接口中的所有方法,Collection系列的集合都有
(2)Collection接口的方法:
A. 添加
add(E obj):添加元素对象到当前集合中
addAll(Collection<?extends E>other)
添加到other集合中的所有元素对象到当前集合中,即this = this∪other
public void test(){
Collection coll = new ArrayList();
//Collection是一个接口,不能直接创建对象,必须创建实现类的对象
//ArrayList是Collection接口的实现类之一
coll.add("hello");
coll.add("world");
}
public void test(){
Collection coll = new ArrayList();
coll.add("hello");
coll.add("world");
Collection other = new ArrayList();
other.add("hello");
other.add("world");
coll.add(other); //把other当成一个整体加入coll中,coll中元素个数为3
coll.addAll(other); //把other的每个元素加入coll中,coll中元素个数为4
}
B.删除
boolean remove(Object obj):
从当前集合中删除第一个找到的与obj对象equals返回true的元素
boolean removeAll(Collection<?> coll):
从当前集合中删除所有与coll集合中相同的元素,即this = this - this ∩ coll
boolean removeIf(Predicate<? super E> filter):
删除满足给足条件的此集合的所有元素
boolean retainAll(Collection<?> coll):
从当前集合中删除两个集合不同的元素,使得当前集合仅保留与c集合中的元素相同的部分
clean();
全部删除
public void test(){
Collection coll = new ArrayList();
coll.add("hello");
coll.add("world");
other.add("java");
Collection other = new ArrayList();
other.add("hello");
other.add("world");
coll.remove("hello"); 只有world和java
coll.removeAll(other); 剩下java
coll.retainAll(other); 剩下hello和world
removeIf的形参是Predicate接口,有一个方法是boolean test(T t);
这个t就是集合中的元素,如果t满足要删除的条件,就返回true
coll.removeIf(new Predicate{
@override
public boolean test(Object o){
return ((String)o).contains("o");
}
});
}
C.查询
int size():
获取当前集合中实际存储的元素个数
boolean idEmpty():
判断当前集合是否为空集
boolean contains(Object obj):
判断当前集合中是否存在一个与obj对象equals返回true的元素
boolean containsAll(Collection<?> c):
判断c集合中的元素是否在当前集合中都存在,即c集合是否是当前集合的“子集”
Object[] toArray():
返回包含当前集合中所有元素的数组
D. 遍历和迭代
5. 迭代器
迭代器就是用来遍历集合元素的对象/工具
java.util.Iterator接口,这是迭代器接口
方法:
boolean hasNext()
判断集合是否还有元素可以迭代
Object next():
取出当前元素,且迭代器往后移动
void remove():
用于删除刚刚迭代的元素
Collection系列的集合中,有一个方法:
Iterator iterator();
这个方法是返回遍历当前集合对象的一个迭代器对象
左边Iterator是接口,右边coll.iterator()方法体中会返回Iterator接口的一个实现类
具体是哪个实现类对象,要看集合类型,
如ArrayList集合类型,返回的是ArrayList类中的Itr内部类,它实现了Iterator接口
Iterator iterator = coll.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
Iterator iterator = coll.iterator;
while(iterator.hasNext()){
String s = (String)iterator.next();
if(s.contains("o")){
iterator.remove();
}
}
6. Iterable和Iterator之间的关系
Iterable接口:实现这个接口允许对象称为“foreach”语句的目标(JDK1.5)
数组默认实现这个接口
Collection接口也继承了这个接口,则Collection系列的集合实现类都实现了Iterable接口
Iterator:接口有一个抽象方法
Iterator Iterator()——说明foreach循环本质上还是依赖于java.util.Iterator接口,或者说,本质上就是用它
7. 集合元素的删除
集合中会有一个modCount,它是int类型,原来记录集合元素个数变化的次数
添加一个元素,modCount++
删除一个元素,modCount++
替换一个元素,modCount不变
具体看源码
结论:
不要在foreach遍历过程中删除元素,添加元素
不要在Iterator迭代器遍历集合时,用集合的删除、添加方法修改元素个数
可以在Iterator迭代器遍历集合时,使用迭代器自己的remove或add方法添加元素
建议removeIf
8.练习
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
import java.util.function.Predicate;
public class exer2 {
public static void main(String[] args) {
//创建一个叫primeNumbers的集合存数
Collection primeNumbers = new ArrayList();
//将1-100的指数都存入这个集合中
for(int i = 2;i<100;i++){
boolean flag = true;
for(int j = 2;j<i;j++){
if(i%j == 0){
flag = false;
break;
}
}
if(flag) {
primeNumbers.add(i);
}
}
//查看有多少个
System.out.println("个数为:"+primeNumbers.size());
//使用foreach遍历
for (Object primeNumber : primeNumbers) {
System.out.print(primeNumber+",");
}
System.out.println();
//用Iterator迭代器删除个位数是3的质数
Iterator iterator = primeNumbers.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
Integer num = (Integer)next;
if(num%10 == 3){
iterator.remove();
}
}
//判断primeNumbers集合中是否有11,如果有,用Collection的remove删除
primeNumbers.remove(11);
//用removeIf删除个位数为7的质数
primeNumbers.removeIf(new Predicate() {
@Override
public boolean test(Object o) {
Integer num = (Integer)o;
return num%10 ==7;
}
});
//再次用Iterator遍历剩下的质数
iterator = primeNumbers.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.print(next+",");
}
System.out.println();
//创建另一个Collection集合randNumbers
Collection randNumbers = new ArrayList();
//添加10个100以内的随机整数
Random random = new Random();
for(int i = 0;i<10;i++){
randNumbers.add(random.nextInt(100));
}
//使用foreach遍历randNumbers集合的随机数
for (Object randNumber : randNumbers) {
System.out.print(randNumber+",");
}
System.out.println();
//求它们的交集
primeNumbers.retainAll(randNumbers);
System.out.print(primeNumbers+",");
}
}