Java基础学习
一、不可变集合
不可变集合
:就是不可以改变集合内容,长度
运用场景:
书写格式:
- 在List、Set、Map接口中,都存在静态的of方法,可以获取一个不可变的集合。
主要方法
方法名称 | 说明 |
---|---|
static List of(E…elements) | 创建一个具有指定元素的List集合对象 |
static Set of(E…elements) | 创建一个具有指定元素的Set集合对象 |
static <K .V> Map<K,V> of(E…elements) | 创建一个具有指定元素的Map集合对象 |
注意:
List直接使用
Set: 元素不能重复
Map: 元素不能重复、键值对数量最多是10个 超过10个用ofEntries方法
二、Stream流
Stream流的使用步骤:
2.1 Stream流数据添加
package Stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.stream.Stream;
public class StreamCreat {
public static void main(String[] args) {
//创建一个单列集合的Stream流
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list,2,3,5,4);
list.stream().forEach(s-> System.out.println(s));
//创建一个双列的集合
HashMap<String,Integer> hm = new HashMap<>();
hm.put("黄埔",111);
hm.put("们都",222);
hm.put("阿松大",333);
hm.put("o",444);
hm.keySet().stream().forEach(s-> System.out.println(s));
//创建一个数组
String[] arr = {"as","asd","asdasdas","xzca","wad"};
Arrays.stream(arr).forEach(s-> System.out.println(s));
//零散的数据
Stream.of(1,2,3,4).forEach(s-> System.out.println(s));
}
}
注意:
2.2 Stream流的中间方法
注意:
package Stream;
import java.util.ArrayList;
import java.util.Collections;
public class StreamContent {
public static void main(String[] args) {
//创建方法,并且添加数据
ArrayList<String> list1 = new ArrayList<>();
Collections.addAll(list1,"张阿松大-22","黄阿松-11","西欧我-33","黄阿萨-87","阿萨松-33","阿萨松-12","阿萨松-32","阿萨松-32");
//过滤方法
list1
.stream()
.filter(s->s.startsWith("黄"))
.forEach(s-> System.out.println(s));
//获取前面几个数据
list1.stream().limit(3).forEach(s-> System.out.println(s));
//跳过前面几个数据
list1.stream().skip(3).forEach(s-> System.out.println(s));
//集合去重
list1.stream().distinct().forEach(s-> System.out.println(s));
//合并a,b,两个集合
// Stream.concat(list1,list1);
//转化流的数据类型
list1.stream().map(s->Integer.parseInt(s.split("-")[1])).forEach(s-> System.out.println(s));
}
}
2.3 Stream终结方法
package Stream;
import java.util.*;
import java.util.stream.Collectors;
public class StreamCollect {
public static void main(String[] args) {
//创建Arraylist集合
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张无忌-女-18","张强-男-87","张三丰-男-21","张翠山-女-18","张良-男-18","王二麻子-女-15","谢广坤-女-18");
//用Arraylist接收
List<String> collect = list.stream()
.filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toList());
System.out.println(collect);
//用Set接收(里面不能有重复的元素)
Set<String> Set = list.stream()
.filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toSet());
System.out.println(Set);
//用map接收
Map<String, Integer> map = list.stream().filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toMap(
s -> s.split("-")[0]
,
s -> Integer.parseInt(s.split("-")[2])
));
System.out.println(map);
}
}
IntFunction的泛型
: 具体类型的数组
apply的形参:流中数据的个数,要跟数组的长度保持一致
apply的返回值: 具体类型的数组方法体: 就是创建数组
toArray方法
的参数的作用: 负责创建一个指定类型的数组
toArray方法
的底层,会依次得到流里面的每一个数据,并把数据放到数组中
toArray方法
的返回值: 是一个装着流里面所有数据的数组
toMap:
参数一:
参数二:
三、 方法引用
3.1 方法引用的基本概念
概念:把已经有的方法拿过来用,当做函数式接口中抽象方法的方法体
方法引用
::是什么符号?
方法引用符
package Stream.方法引用;
import java.util.Arrays;
import java.util.Comparator;
public class funcationDom1 {
public static void main(String[] args) {
//创建一个数组,随机添加数据,最后的数据要是按降序的排列
Integer[] arr = {1,8,26,9,3,95};
//1. 通过匿名内部类的形式进行排序
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
// 2. 通过lambda的形式进行排序
Arrays.sort(arr,(o1,o2) -> o2-o1);
//3. 通过引用函数的形式来进行排列
Arrays.sort(arr,funcationDom1::subtraction);
System.out.println(Arrays.toString(arr)); //[95, 26, 9, 8, 3, 1]
}
public static int subtraction(int num1 , int num2){
return num2 - num1;
}
}
3.2 方法引用的分类
- 引用静态方法
- 引用成员方法
- 引用构造方法
- 其他调用方式
3.2.1 引用静态方法
格式:类名::静态方法
范例:
Integer::parseInt
package Stream.方法引用;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class Dom2 {
public static void main(String[] args) {
//创建集合,将数组当中的字符串变为int类型
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"1","2","3","4","56");
//1. 利用匿名内部类
list.stream()
.map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s);
}
}).forEach(s-> System.out.println(s));
//2. 利用调用静态方法来实现
list.stream()
.map(Integer::parseInt).forEach(s-> System.out.println(s));
}
}
3.2.2 引用成员方法
格式:对象::成员方法()
其他类:其他类对象::方法名
本类: this::方法名
父类: super::方法名
其他类:
list.stream()
.filter(new StringOperration()::StringJudge)
.foreach(s->system.out.printIn(s));
本类:
list.stream()
.filter(this::StringJudge)
.foreach(s->system.out.printIn(s));
父类:
list.stream()
.filter(super::StringJudge)
.foreach(s->system.out.printIn(s));
3.2.3 引用构造方法
格式:类名::new
范例:
student::new
package Method_reference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
public class Dome6 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张三,12","李四,12","王五,12");
//原先的方法使集合里面的数据转换为对象类型的
list.stream().map(new Function<String, Student>() {
@Override
public Student apply(String s) {
String[] split = s.split(",");
String name = split[0];
int age = Integer.parseInt(split[1]);
return new Student(name,age);
}
}).forEach(s-> System.out.println(s));
//使用引用构造方法map集合
list.stream().map(Student::new).forEach(s-> System.out.println(s));
}
}
package Method_reference;
public class Student {
private String name;
private int age;
public Student() {
}
//重写一个带一个参数的构造函数
public Student(String str){
String[] split = str.split(",");
this.name = split[0];
this.age = Integer.parseInt(split[1]);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
3.2.4 使用类名引用成员方法
格式:类名::成员方法
范例:
String::substring
将集合当中的所有数据全部变成大写输出
package Stream.方法引用;
import java.util.ArrayList;
import java.util.Collections;
public class Dom3 {
public static void main(String[] args) {
//创建Arraylist对象并且添加对象
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"aaa","bbb","ccc");
//将所有的字母变成大写并且输出
//.map(String::toUpperCase) : 表示拿着stream里面的每一个数据去调用String方法里面的toUpperCase
list.stream()
.map(String::toUpperCase)
.forEach(s-> System.out.println(s));
//方法二
/* list.stream()
.map(new Function<String, String>() {
@Override
public String apply(String s) {
return s.toUpperCase();
}
}).forEach(s-> System.out.println(s));
*/
}
}
3.2.5 引用数组的构造方法
格式:数据类型I::new
范例:
int[]::new
集合中存储一些整数,收集到数组当中:
数组的类型,需要跟流中数据的类型保持一致。
package Stream.方法引用;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;
public class Dom4 {
public static void main(String[] args) {
//创建集合,添加整型数据
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list,1,2,3,4,5);
//将数据添加到数组当中
Integer[] array = list.stream()
.toArray(Integer[]::new);
System.out.println(Arrays.toString(array));//[1, 2, 3, 4, 5]
//法二:
Integer[] arr = list.stream()
.toArray(new IntFunction<Integer[]>() {
@Override
public Integer[] apply(int value) {
return new Integer[value];
}
});
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5]
}
}
四、异常
4.1 异常
异常
:异常就是代表程序出现的问题
当出现异常时,该怎么处理事情
Exception
:叫做异常,代表程序可能出现的问题我们通常会用Exception以及他的子类来封装程序出现的问题运行时异常
:RuntimeException及其子类,编译阶段不会出现异常提醒运行时出现的异常(如:数组索引越界异常编译时异常
:编译阶段就会出现异常提醒的。 (如:日期解析异常)
4.1.1 运行时异常和编译时异常的区别
4.1.2 异常的作用
-
作用一
: 异常是用来查询bug的关键参考信息 -
作用二
: 异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况
搭建的条件
public void setAge(int age) {
if (age>40 || age<18){
throw new RuntimeException();
}else {
this.age = age;
}
}
初始:
package 异常;
public class Dom1 {
public static void main(String[] args) {
//创建对象
Student s = new Student("zhangsn",13);
s.setAge(90);
}
}
结果
4.2 异常处理方式
- JVM默认的处理方式
- 自己处理
- 抛出异常
4.2.1 JVM默认的处理方式
代码:
package 异常;
public class Dom1 {
public static void main(String[] args) {
//创建对象
Student s = new Student("zhangsn",13);
System.out.println("我先执行一步");
s.setAge(90);
System.out.println("看看我执行没");
}
}
控制台报错,并且不会执行后面代码
4.2.2 自己处理
格式:
try {
可能出现异常的代码;
catch(异常类名 变量名){
异常的处理代码;
原理解释:
package 异常;
public class Dom2 {
public static void main(String[] args) {
//创建对象
int[] arr = {1,2,3,4,5};
System.out.println("我先执行一步");
try {
System.out.println(arr[5]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("出现错误,错误信息:"+e);
}
System.out.println("看看我执行没");
}
}
控制台:
该方法好处,就是可以执行下面的代码
常见问题
- 如果try中可能会遇到多个问题,怎么执行?
如果再出现多个异常时,要把父类写在最后一个
因为如果父类放到最前面的话,会将其子类所有的异常都接收
package 异常;
public class Dom3 {
public static void main(String[] args) {
int[] arr = {1,2,34,5,51};
try {
System.out.println(1/0);
System.out.println(arr[5]);
String s = null;
System.out.println(s.equals("asd"));
}catch (NullPointerException e){
System.out.println("空指针异常");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("索引越界");
}catch (ArithmeticException e){
System.out.println("分母不为");
}
System.out.println("看看我执行了吗s");
}
}
执行时机是,捕捉到就跳转,不会执行try该代码下面的代码,直接去catch当中查询其捕捉到的异常,若无就会是JVM自动给你报错,导致后面的代码无法实现
4.3 Throwable 的成员方法
方法名称 | 说明 |
---|---|
public string getMessage() | 返回此 throwable 的详细消息字符串 |
public String tostring() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
快捷键生成try……catch --> ctrl + Alt + t
package 异常;
public class Dom4 {
public static void main(String[] args) {
//创建对象
int[] arr = {1,2,3,4,5};
System.out.println("我先执行一步");
try {
System.out.println(arr[5]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e.getMessage());//Index 5 out of bounds for length 5
System.out.println(e.toString());//java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
e.printStackTrace();//打印红色报错,包含上面两个信息+出错位置。他还不会影响到后面代码的实现
}
System.out.println("看看我执行没");
}
}
4.4 抛出异常
代码实现
GirlFrend代码细节地方:
public void setName(String name) {
int len = name.length();
if (len<3 || len>10){
throw new RuntimeException();//运行时错误
}
this.name = name;
}
public void setAge(int age) {
if (age>40 || age<18){
throw new RuntimeException();
}
this.age = age;
}
main代码:
package 异常;
import java.util.Scanner;
public class Exercise {
public static void main(String[] args) {
//键盘录入女朋友名字(长度3-10)和年龄(18-40)
Scanner sc = new Scanner(System.in);
GirlFriend gf = new GirlFriend();
while (true) {
try {
System.out.println("请输入你女朋友的名字");
String name = sc.nextLine();
System.out.println("请输入你女朋友的年龄");
String agestr = sc.nextLine();
int age = Integer.parseInt(agestr);
gf.setAge(age);
gf.setName(name);
break;
} catch (NumberFormatException e) {
System.err.println("数字格式有错,请重新输入");
}catch (RuntimeException e){
System.err.println("名字有误 或 年龄有误");
}
}
System.out.println("女朋友的年龄"+gf.getAge() + "女朋友名字" + gf.getName());
}
}
4.5 自定义异常
防止再出现异常时,没有适合说明异常的工具
书写步骤:
AgeOutAreaException
package 异常;
public class AgeOutAreaException extends RuntimeException{
public AgeOutAreaException() {
}
public AgeOutAreaException(String message) {
super(message);
}
}
NameFormatException
package 异常;
public class NameFormatException extends RuntimeException{
public NameFormatException() {
}
public NameFormatException(String message) {
super(message);
}
}
public void setName(String name) {
int len = name.length();
if (len<3 || len>10){
throw new RuntimeException(name + "范围为长度3-10");//运行时错误
}
this.name = name;
}
public void setAge(int age) {
if (age>40 || age<18){
throw new RuntimeException(age +"超出范围") ;
}
this.age = age;
}