导入项目代码:
1.找到你当前idea的项目路径
路径打开后是这个:
2.然后将要拷贝的项目粘贴到该目录下
3.在idea中导入项目,导入步骤如下:
然后找到要导入的项目,打开导入iml文件,之后点击ok即可
注意:拷贝项目时如果要导入的项目已在idea项目目录下的话,需要把之前的同名的项目删除再拷贝。
集合进阶:
双列集合:
双列集合的特点:键和值是一一对应的
Map常见的API:
put()方法细节:
添加数据时如果键不存在,那么会将键值对对象添加到map集合中
添加数据时如果键存在,那么会把原有的键值对对象覆盖,并返回覆盖的值
Map的遍历方式:
1.通过键找值:
map.keySet(); //返回的是set集合
2.键值对遍历
map.entrySet(); //返回值是Set集合
3.Map的Lambda表达式遍历;
Map的实现类:HashMap
HashMap的特点:
HashMap的底层原理:
数据结构和HashSet一样都是数组+链表+红黑树的结构,满足数组长度>=64,链表长度=8的条件后转为红黑树存储。
在map.put()即添加数据的时候,会先看数组中是否为空,为空了直接添加键值对对象entry,不为空的话会.equals()判断键值key是否一致,一致了会覆盖原有值,不一致了会挂在原来数据后。
m.get(key);获取的是key值对应的value值
HashMap<String,Integer> m=new HashMap<>();
for (String s1 : list) {
if(m.containsKey(s1)){
int count = m.get(s1);
count++;
m.put(s1,count);
}else {
m.put(s1,1);
}
}
LinkedHashMap:
TreeMap:
查看源码的小细节:
前面小圆圈里是C指的是类
m指的是方法
f(filed)指的是属性:成员变量、常量
可变参数:
方法形参的个数是可以变化的
在方法的形参当中最多只能写一个可变参数
Collections:
不是集合,是集合的工具类
微服务架构:
编程中的对应关系:
创建不可变的集合:
不可变集合:不可以被修改的集合
Stream流:
Stream流的思想:
像一个流水线一样不断的过滤不合格的条件:
Stream流的作用:
Stream流的使用步骤:
Stream.of()方法细节:
方法的形参是一个可变参数,可以传递一堆零散的数据也可以传递数组,
但是数组必须是引用数据类型,如果传递的是基本数据类型,是会把整个数组当成一个元素,放到Stream中。比如int[] 数组打印出来是一个地址值。
Stream流的中间方法:
Stream流的终结方法:
toArray()收集流中的数据放到数组中:
collect收集流中的数据放到集合中:
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"张-男-20","张三-男-20","张1-男-20");
// Object[] objects = list.stream().toArray();
// System.out.println(Arrays.toString(objects));
//收集所有男性信息
//collect收集流中的数据以list集合存储
List<String> newlist = list.stream().filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toList());
System.out.println(newlist);
//collect收集流中的数据以set集合存储
Set<String> set = list.stream().filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toSet());
System.out.println(set);
//collect收集流中的数据以Map集合存储
Map<String, Integer> map = list.stream().filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
String s1 = s.split("-")[0];
return s1;
}
},
new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[2]);
}
}));
System.out.println(map);
collect收集到map集合中改写为的Lambda表达:
方法引用:
方法引用的分类:
引用静态方法:
引用成员方法:
注意静态的方法中不能调用this关键字。
引用构造方法:
ArrayList<String> list=new ArrayList<>();
Collections.addAll(list,"张无忌,12","张,22","张无,36","张忌,55","张无忌1,100");
// List<Person> list1 = list.stream().map(new Function<String, Person>() {
// @Override
// public Person apply(String s) {
// String name = s.split(",")[0];
// int age = Integer.parseInt(s.split(",")[1]);
// return new Person(name, age);
// }
// }).collect(Collectors.toList());
// System.out.println(list1);
list.stream().map(Person::new).forEach(s-> System.out.println(s));
}
class Person{
private String name;
private int age;
public Person() {
}
public Person(String str) {
this.name = str.split(",")[0];
this.age = Integer.parseInt(str.split(",")[1]);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Person{name = " + name + ", age = " + age + "}";
}
}
其他调用方式:
方法引用注意事项:
1.需要有函数式接口
2.被引用的方法必须已存在
3.被引用的方法的形参和返回值必须与抽象方法保持一致
4.被引用方法的功能要满足当前需求
而类名::成员方法引用规则(是这种方式独有的):
简而言之如果跟抽象方法中形参不一致,则只需要跟抽象方法中的第二个形参到最后一个形参保持一致。
结合下图String::toUpperCase()解读
首先方法是空的形参,和抽象方法中第二个到最后一个的形参也是空的形参,两者一致
其次抽象方法中的第一个形参是String s,那么使用这种方式进行方法引用,只能引用String这个类中的方法,即抽象方法的第一个形参是什么就只能引用什么类型的方法。
局限性:
不能引用所有类中的成员方法。
是跟抽象方法的第一个参数有关,这个参数是什么类型的,那么就只能引用这个类中的方法。
引用数组的构造方法:
细节:数组的类型,需要跟流中数据的类型保持一致。
ArrayList<Integer> list=new ArrayList<>();
Collections.addAll(list,1,2,3);
Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {
@Override
public Integer[] apply(int value) {
return new Integer[value];
}
});
Integer[] arr2 = list.stream().toArray(Integer[]::new);
System.out.println(Arrays.toString(arr));
异常:
编译时异常:在编译阶段必须手动处理,否则代码报错。
运行时异常:在编译阶段是不需要处理的,是代码运行时出现的异常
异常的作用:
如在遇到想把问题通知给调用者时可以用:throw RuntimeException;
异常的处理方式:
1.JVM默认的处理方式
2.自己处理
3.抛出异常
JVM的默认处理方式:
自己处理(捕获异常):
一问:如果try中没有遇到问题怎么执行?
答:会把try中所有的代码执行完毕,不会执行catch里面的代码
注意:只有在出现异常的时候才会执行catch里面的代码。
二问:如果try中可能会遇到多个问题,怎么执行?
答:会写多个catch与之对应,如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面。
了解性:在JDK7以后,我们可以在catch中同时捕获多个异常,中间用单竖线 | 隔开,表示如果出现A异常或者B异常的话,采取同一种处理方式。