一、String概述:
1、java.lang.String类代表字符串,String类定义的变量可以用于指向字符串对象,然后操作该字符串。
2、java程序中的所有字符串文字(如"abc")都为此类的对象。
String name = "张三";
String school = "野鸡大学";
二、String类的特点:
1、String其实常被称为不可变字符串类型,它的对象在创建后不能被更改。
先把main方法加载到栈内存,执行第一行代码,创建了一个字符串对象放在常量池中,将此时的字符串地址传给name,再执行第二行,还是把"教育加载到常量池",但通过累加得到的"传智教育"将放在堆内存中,并且此时的name将指向它,下面那行累加也是这个道理。因为String类重写了Object类的toString()方法,所以返回值是字符串的内容而不是地址值。
三、String类常用API
1、判断字符串是否相等
a、字符串内容的比较不适合用"=="比较。因为"=="比较的是地址值,而不是内容。
b、String类可以使用equals()比较:只关心内容是否一样。
c、equalsIgnoreCase(),可以忽略大小写比较。
2、其他常用API
方法名 说明
length() 获取字符串的长度
char At(int index) 返回下标所在的cha值(字符)
char[] toCharArry() 将当前字符串转换成字符数组返回
String substring(int beginIndex,int endIndex) 根据开始和结束索引进行截取,取得新的字符串(包前不包后)
String substring(int beginIndex) 从传入的索引进行截取,截取到末尾,得到新的字符串
String replace(CharSequence target,CharSequence replacement) 使用新值,将字符串中的旧值替换,得到新的字符串
String[] split(String regex) 根据传入的规则切割字符串,得到字符串数组返回
boolean contains(CharSequence s) 判断某一字符串是否包含另一字符串
四、集合体系
1、集合类体系结构
Collection集合体系:
集合都是支持泛型的,可以在编译阶段约束集合只能操作某种类型数据。
Collection集合的遍历方式:
方式一:迭代器
public static void main(String[] args) {
Collection<Integer> score = new ArrayList<>(); //多态写发
score.add(98);
score.add(77);
score.add(66);
score.add(89);
score.add(79);
score.add(50);
score.add(100);
Iterator<Integer> it = score.iterator();
//先判断是否有元素
while (it.hasNext()){
//取元素
int s = it.next();
System.out.print(s+" ");
}
}
输出结果:
98 77 66 89 79 50 100
方式二:foreach/增强for循环
public static void main(String[] args) {
Collection<Integer> score = new ArrayList<>(); //多态写发
score.add(98);
score.add(77);
score.add(66);
score.add(89);
score.add(79);
score.add(50);
score.add(100);
for (Integer s:score) {
System.out.println(s);
}
}
}
输出结果同上。
方式三:lambdabds
public static void main(String[] args) {
Collection<Integer> score = new ArrayList<>(); //多态写发
score.add(98);
score.add(77);
score.add(66);
score.add(89);
score.add(79);
score.add(50);
score.add(100);
score.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
}
}
结果同上。
ArrayList集合
集合是与数组类似,也是一种容器,用于装数据。是集合中的一种,支持索引。
1、集合的特点:
a、大小不固定,启动后可以动态变化、类型也可以选择不固定。数组的大小是固定的,不可以动态变化。
b、非常适合做元素不确定,且要进行增删查改的业务场景。
2、集合的具体使用
(1)、快速入门:
a、创建ArrayList集合的对象:
ArrayList 集合名 = new ArrayList(); //可以储存任何类型
b、添加对象
add(),返回值类型是boolean
add(int index,E element) 在指定位置插入一个新元素
(2)、对泛型的支持
ArrayList<E>:其实就是一个泛型类,可以在编译阶段约束集合对象只能操作某种数据类型。
例如:
ArrayList<String>:此集合只能操作字符串类型的元素。
ArrayList<Integer>:此集合只能操作整数类型的元素。
注意:集合只能储存引用类型,不支持基本数据类型。
1、集合常用API
方法名称 说明
E get(int index) 返回指定索引处的元素
int size() 返回集合中的元素的个数
E remove(int index) 删除指定索引处的元素,返回被删除的元素
boolean remove(Object o) 删除指定的元素,返回删除是否成功
E set(int index ,E element) 修改指定索引处的元素,返回被修改的元素
2、遍历并删除元素
分析 :
因为需要有增删查改的功能,所以应用集合存,其次是通过遍历去找到低于80的元素然后删掉。
具体实现:
public static void main(String[] args) {
//创建一个集合储存学生的分数
ArrayList<Integer> score = new ArrayList<>();
score.add(98);
score.add(77);
score.add(66);
score.add(89);
score.add(79);
score.add(50);
score.add(100);
//输出
System.out.println(score);
}
}
输出的应该是:
[98, 77, 66, 89, 79, 50, 100]
再对其进行删除操作:
for (int i = 0; i < score.size(); i++) {
int s = score.get(i);
if(s<80){
score.remove(i);
}
}
System.out.println(score);
输出结果为:
[98, 66, 89, 50, 100]
我们发现,这里出现了一个bug,并没有把全部低于八十分一下的删除,原因是什么呢?
因为,当判断到77时,会把它删掉,删掉后77后面的元素会往前移,但是这里i加了1,这样就跳过了66,直接去判断89了,之后又删掉了79,跳过了50。那该怎么解决呢?如下:
解法一:
for (int i = 0; i < score.size(); i++) {
int s = score.get(i);
if(s<80){
score.remove(i);
//每删除成功之后让i退一步,这样可以保证下次再回到这个位置,不会跳过元素
i--;
}
}
System.out.println(score);
}
这里输出结果是正确的:
[98, 89, 100]
解法二:
//从后面到着遍历
for (int i = score.size()-1; i >= 0 ; i--) {
int s = score.get(i);
if(s<80){
score.remove(i);
}
}
System.out.println(score);
}
List集合
用法大体相同,不在介绍。
六、Set集合
HashSet
HashSet实现Set接口,底层由HashMap(后面讲解)来实现,为哈希表结构,新增元素相当于HashMap的key,value默认为一个固定的Object。在我看来,HashSet相当于一个阉割版的HashMap;
当有元素插入的时候,会计算元素的hashCode值,将元素插入到哈希表对应的位置中来;
它继承于AbstractSet,实现了Set, Cloneable, Serializable接口。
(1)HashSet继承AbstractSet类,获得了Set接口大部分的实现,减少了实现此接口所需的工作,实际上是又继承了AbstractCollection类;
(2)HashSet实现了Set接口,获取Set接口的方法,可以自定义具体实现,也可以继承AbstractSet类中的实现;
(3)HashSet实现Cloneable,得到了clone()方法,可以实现克隆功能;
(4)HashSet实现Serializable,表示可以被序列化,通过序列化去传输,典型的应用就是hessian协议。
具有如下特点:
-
不允许出现重复因素;
-
允许插入Null值;
-
元素无序(添加顺序和遍历顺序不一致);
-
线程不安全,若2个线程同时操作HashSet,必须通过代码实现同步;
TreeSet集合特点和概述:
a:不重复、无索引、可排序。
b:可排序:按照元素的大小默认升序(由大到小)排序。对于数值类型:Integer、Doubl,官方默认按照大小进行升序排序。对于字符串类型:默认按照首字母的编号升序排序,若首字母相同,则看第二个,依次类推,若都相同,则看字符串长度。
c:TreeSet集合底层是基于红黑树的数据结构实现排序的,增删查改性能都很好。
注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。对于自定义的Student对象,TreeSet无法直接排序,要想使用,则需要制定排序规则,并且需要实现Comparable。如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较排序。例如:
//学生类实现Comparable接口,TreeSet就可以对学生进行自然排序
public class Student implements Comparable<Student>{
private String name;
private int age;
//实现元素排序的规则
/*
根据返回值排序
返回的负数,认为当前要存入的元素比较小,存左边
返回的正数,认为当前要存入的元素比较大,存右边
返回的0,认为当前要存入的元素已经存在,不存入
*/
@Override
public int compareTo(Student o) {
//按照年龄升序排序 (从小到大)
return this.age - o.age;
//按照年龄降序排序(从大到小)
//return o.age - this.age;
}
测试类:
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<>();
ts.add(new Student("lisi",21));
ts.add(new Student("zhangsan",28));
ts.add(new Student("zhaoliu",25));
Iterator<Student> it = ts.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+":"+s.getAge());
}
}
}
输出结果:
lisi:21
zhaoliu:25
张三:28