项目整体概图
1 Lambda表达式
1.1 概述:只有一个抽象方法的接口
1.2 【比较】lambda表达式、匿名内部类
1.3 基本语法
(参数)->表达式 或 (参数)->{方法体;}
(1)形参列表
形参列表允许省略形参类型,如形参列表中只有一个参数,形参列表的圆括号也可以省略
(2)箭头(->)
必须通过英文的划线号和大于符号组成
(3)代码块
如果代码块中只包含一条语句,则lambda表达式允许省略代码块的花括号
(4)返回值
如果代码块只有一条return语句,则可以省略return关键字
(5)函数形参
lambda表达式可以直接作为函数的参数
(6)lambda表达式类型
- Lambda表达式的类型(也被称为"目标类型(target type)"),Lambda表达式的目标类型必须是"函数式接口(functional interface)"。
- 函数接口(Java 8新引入的概念),定义:只有一个显示声明抽象方法的接口
- 函数接口通常使用@FunctionalInterface标注出来 (也可以不标记),函数式接口可以包含多个default或static方法,但是只能声明一个抽象方法,@FuctionalInterface主要作用就是检查当前接口是不是函数接口
- 若想使用lambdaname目标必须是一个函数接口
(7)lambda表达式中变量的使用
如果是全局的变量直接用,如果是局部变量会被默认在前面添加final(被作为常量,类似于局部变量在局部内部类中使用的情况)
1.4 【样例】
import org.junit.Test;
public class Demo2 {
public static void main(String[] args) {
fun();
}
//@Test
public static void fun() {
//1.没有参数的
InterA a = ()->{
System.out.println("没有参数");
};
a.showA();
//简化
InterA aa = ()->System.out.println("没有参数");
aa.showA();
//2.一个参数的
InterB b = (ib)->{
System.out.println("一个参数:"+ib);
};
b.showB(4);
//简化
InterB bb = (ib)->System.out.println("一个参数:"+ib);
bb.showB(5);
//3.两个参数的
InterC c = (ia,ib)->{
int sum = ia+ib;
System.out.println("两个参数:"+" ia:"+ia+" ib:"+ib+" sum:"+sum);
};
c.showC(4, 6);
//简化
InterC cc = (ia,ib)->System.out.println("两个参数:"+" ia:"+ia+" ib:"+ib);
cc.showC(4, 5);
//4.返回值
InterD d = (i,j)->{
int sum = i+j;
//System.out.println("sum:"+sum);
return sum;
};
int value = d.showD(4, 6);
System.out.println(value);
//简化 简化版的不需要写return
InterD dd = (i,j)->i+j;
int value1 = dd.showD(4, 7);
System.out.println(value1);
//5.lambda表达式作为参数
fun2(
new InterC() {public void showC(int a, int b) {}}
);
fun2((i,j)->System.out.println("lambda表达式作为参数"+" i:"+i));
//7.lambda表达式中变量的使用
String value11 = "hello world";
InterA aaa = ()->{
System.out.println(value11);
//value11是final类型的是一个常量,值是不能改变的
//value11 = "haha";
};
aaa.showA();
}
public static void fun2(InterC c) {
c.showC(4, 6);
}
}
interface InterA{
public void showA();
}
interface InterB{
public void showB(int a);
}
interface InterC{
public void showC(int a,int b);
}
interface InterD{
public int showD(int a,int b);
}
@FunctionalInterface
interface InterE{
public int showD(int a,int b);
//public int showY(int a,int b);
}
1.5 方法引用与构造器引用
1.5.1 引用类方法
1.5.2 引用特定对象的实例方法
1.5.3 引用某类对象的实例方法
1.5.4 引用构造方法
1.6 【代码】
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
interface Inter{
public void eat();
}
class DaHuang implements Inter{
public void eat() {
System.out.println("eat");
}
}
public class Demo4 {
public static void main(String[] args) {
//遍历集合
String[] strings = {"java","html","BigData","python"};
List<String> list = Arrays.asList(strings);
//原理的遍历方法
for (String string : list) {
System.out.println(string);
}
System.out.println("*************");
//通过lambda表达式
list.forEach(string->System.out.println("字符串是:"+string));
//再简化
list.forEach(System.out::println);
//多线程
new Thread(new Runnable() {
public void run() {
System.out.println("通过匿名内部类创建任务");
}
}).start();
//通过lambda表达式
new Thread(()->System.out.println("通过lambda表达式创建任务")).start();
//排序--使用Collections
// Collections.sort(list, new Comparator<String>() {
// public int compare(String o1, String o2) {
// return o1.compareTo(o2);
// }
// });
//使用lambda表达式
Collections.sort(list, (o1,o2)->o1.compareTo(o2));
System.out.println(list);
//动态代理
Inter inter = new DaHuang();
Proxy.newProxyInstance(inter.getClass().getClassLoader(), new Class[] {Inter.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("洗手");
Object object = method.invoke(inter, args);
return object;
}
});
//lambda表达式
Proxy.newProxyInstance(inter.getClass().getClassLoader(), new Class[] {Inter.class},(proxy,method,arg)->{
System.out.println("洗手");
Object object = method.invoke(inter, arg);
return object;
});
}
}
2 集合
2.1 区分集合和数组
2.2 分类
2.3 【比较】List、Set
3 Collection
3.1 定义
Collection collection = new ArrayList<>();
3.2 添加
3.3 删除
3.4 判断
3.5 获取
3.6 集合变数组
4 List
4.1 定义
List list = new ArrayList<>();
4.2 增加
4.3 删除
4.4 修改
4.5 查询
4.6 删除全部对象
4.7 应用
(1)List是有序可重复的,现在要求通过List存储不能重复的数据(可以通过Contains判断)
import java.util.ArrayList;
import java.util.Iterator;
/*
* List的注意点:
* 例题:List是有序可重复的
* 要求:使用List存储数据,但是数据不能重复----利用Contains
*/
public class Demo5 {
public static void main(String[] args) {
ArrayList list = new ArrayList<>();
list.add("java");
list.add("php");
list.add("php");
list.add("html");
list.add("python");
System.out.println(list);
//创建一个新的集合,作为装不重复数据的地方
ArrayList list1 = new ArrayList<>();
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
String object = (String) iterator.next();
//如果list1中不包含当前的元素,就进行添加
if (!list1.contains(object)) {
//当list1中不包换object时,将它添加进来
/*
* 如果判断成立,说明list1中不包含当前的元素
* 工作原理:当添加元素时,会让当前的元素与集合中已有的元素通过equels方法进行一一比较.过程中
* 只要有一次返回true,停止比较.让整个的contains方法返回true.只有所有的比较都返回false,最终
* 才会返回false
*
* 实例:添加第三个元素的时候,调用equals方法的过程
* 第三元素.equals("java") = false 第三元素.equals("php") = true 停止比较
*/
list1.add(object);
}
}
System.out.println(list1);
}
}
5 Vector
5.1 【代码】
import java.util.Enumeration;
import java.util.Vector;
/*
* Vector:
*/
public class Demo3 {
public static void main(String[] args) {
Vector vector = new Vector<>();
vector.add("java");
vector.add("html");
vector.add("hadoop");
vector.add("spark");
vector.add("spark");
System.out.println(vector);
//遍历
//获取一个枚举器
Enumeration enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
Object object = (Object) enumeration.nextElement();
System.out.println(object);
}
}
}
6 LinkedList
6.1 【代码】
import java.util.LinkedList;
/*
* LinkedList:
*/
public class Demo4 {
public static void main(String[] args) {
// LinkedList
// 特有的方法:
LinkedList linkedList = new LinkedList<>();
// addFirst()//始终在首位添加
// addLast()//始终在末尾添加
linkedList.addFirst("java");
linkedList.addLast("html");
linkedList.add("hadoop");
linkedList.add(1, "spark");
linkedList.addFirst("BigData");
System.out.println(linkedList);
// getFirst()//获取的对象不存在会发生异常
// getLast()
linkedList.clear();
String value = (String)linkedList.getFirst();//NoSuchElementException 没有这个元素异常
System.out.println(value);
// removeFirst()//删除的对象不存在会发生异常
// removeLast()
// 从jdk1.6开始出现以下方法
// offerFirst()
// offerLast()
// peekFirst()//获取的对象不存在会返回null
// peekLast()
System.out.println(linkedList.peekFirst());
// pollFirst()//删除的对象不存在会返回null
// pollLast()
}
}
7 Set
7.1 概述
8 HashSet
8.1 【代码】
package com.qf.test;
import java.util.HashSet;
import java.util.Set;
public class Demo7 {
public static void main(String[] args) {
Set set = new HashSet<>();
//说明Set本身的add方法内部实现的去重功能,默认调用的是元素的hashCode和equals方法
//String类已经默认重写了hashCode和equals方法
set.add("java");
set.add("hadoop");
set.add("spark");
set.add("HDFS");
set.add("HDFS");
set.add("Mapreduce");
System.out.println(set);
Set set1 = new HashSet<>();
//* 实例:使用HashSet实现Person对象的存储
// * 比较规则自己指定:按照年龄和姓名比,相同认为是一个人
//* 分析:要重写hashCode和equals方法
set1.add(new Person1("bingbing",18));
set1.add(new Person1("zhangsan",28));
set1.add(new Person1("chenchen",98));
set1.add(new Person1("bingbing",18));
System.out.println(set1);
}
}
class Person1{
String name;
int age;
public Person1() {
super();
// TODO Auto-generated constructor stub
}
public Person1(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person1 [name=" + name + ", age=" + age + "]";
}
//重写hashCode方法
@Override
public int hashCode() {
return name.hashCode()+age*1000;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
//自己制定比较规则:根据年龄和姓名比较
//容错处理
if (!(obj instanceof Person1)) {
throw new ClassCastException("当前的对象不是Person1类型的");
}
//向下转型
Person1 person = (Person1)obj;
return this.name.equals(person.name) && this.age==person.age;
}
}
9 TreeSet
9.1 概述
9.2 【代码】第一种排序去重方式
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class Demo8 {
public static void main(String[] args) {
Set set = new TreeSet<>();
/*
* TreeSet的add方法实现的排序,去重.通过调用元素的compareTo方法
* String类已经实现了Comparable接口
*/
set.add("java");
set.add("hadoop");
set.add("spark");
set.add("HDFS");
set.add("HDFS");
set.add("Mapreduce");
System.out.println(set);
//没有实现Compareble接口的对象不能当做TreeSet的元素,否则报异常ClassCastException
Set set1 = new TreeSet<>();
set1.add(new Person2("bingbing",18));
set1.add(new Person2("zhangsan",28));
set1.add(new Person2("chenchen",98));
set1.add(new Person2("bingbing",18));
System.out.println(set1);
}
}
class Person2 implements Comparable{
String name;
int age;
public Person2() {
super();
// TODO Auto-generated constructor stub
}
public Person2(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person2 [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Object o) {
//根据自己制定的规则比较
//根据年龄和姓名比较
//容错处理
if (!(o instanceof Person2)) {
throw new ClassCastException("类型转换错误");
}
//向下转型
Person2 person2 = (Person2)o;
//先比姓名
int num = this.name.compareTo(person2.name);
//再按照年龄比
return num==0?this.age-person2.age:num;
}
}
9.3 【代码】第二种排序去重方法(比较器)
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
/*
* TreeSet的第二种排序去重方法
*
* 使用实现了Comparator接口的compare()方法的比较器对象进行比较
*
* 总结:一个有两种方式
* 第一种让元素实现Comparable接口----自然排序
* 第二种创建实现了Comparator接口的比较器----人工排序
*
* 注意:人工排序的优先级高于默认排序
*
*/
public class Demo9 {
public static void main(String[] args) {
//创建比较器对象
ComStrWithLength comStrWithLength = new ComStrWithLength();
//将比较器对象交给TreeSet
Set set = new TreeSet<>(comStrWithLength);
/*
* TreeSet的add方法实现的排序,去重.通过调用元素的compareTo方法
* String类已经实现了Comparable接口
*/
set.add("java");
set.add("hadoop");
set.add("spark");
set.add("HDFS");
set.add("HDFS");
set.add("Mapreduce");
System.out.println(set);
}
}
//创建一个比较器类
class ComStrWithLength implements Comparator{
@Override
public int compare(Object o1, Object o2) {
//比较字符串的长度
if (!(o1 instanceof String)) {
throw new ClassCastException("类型转换错误");
}
if (!(o2 instanceof String)) {
throw new ClassCastException("类型转换错误");
}
//向下转型
String s1 = (String)o1;
String s2 = (String)o2;
//先按照长度比
int num = s1.length()-s2.length();
//长度相同,再按照字典顺序比
return num==0?s1.compareTo(s2):num;
}
}
10 泛型
10.1 概述:通过<数据类型>接收一种数据类型,在编译的时候会使用这种数据类型检测集合中的元素,如果元素不是<>中规定的类型,就不允许添加到当前的集合中(编译失败)
10.2 作用
(1)使用了泛型不再需要进行容错处理,向下转型,强制类型转换----简化代码
(2)将运行阶段的问题提前到编译阶段检查,提高了代码的安全性和编程效率
10.3 泛型可以修饰的地方:类、方法、接口
10.3.1 【代码】泛型应用在类上
/*
* 泛型应用在类上
*/
public class Demo11 {
public static void main(String[] args) {
Phone phone = new Phone("华为");
Computer computer = new Computer("苹果");
//使用泛型前
Student student = new Student();
student.setTools(phone);// tools = phone 多态
Tools tools = student.getTools(); //多态
Phone phone2 = (Phone)tools;//向下转型
phone2.callPhone();
Computer computer2 = (Computer)tools;//向下转型应该报错但没有报错,原因是多态-所以编译阶段未报错
//使用泛型后
//当泛型确定后,类型就确定了.
Student1<Phone> student1 = new Student1<>();
student1.setTools(phone);
//student1.setTools(computer);
student1.getTools();
}
}
//使用泛型后
/*
* 给Student类加泛型,方式:在类的后面直接添加<E>,E代表任意一种数据类型,注意:这里不一定是E,任意字母都可以
* 这就是在类上使用泛型
* 在类上确定的泛型可以直接在方法上使用
*
* 当泛型没有指定时默认是Object
*/
class Student1<E>{
E tools;
public E getTools() {
return tools;
}
public void setTools(E tools) {
this.tools = tools;
}
}
//使用泛型前
class Student{
Tools tools;
public Tools getTools() {
return tools;
}
public void setTools(Tools tools) {
this.tools = tools;
}
}
class Tools{
String name;
}
class Computer extends Tools{
public Computer() {
}
public Computer(String name){
this.name = name;
}
}
class Phone extends Tools{
public Phone() {
}
public Phone(String name) {
this.name = name;
}
public void callPhone() {
System.out.println("打电话");
}
}
10.3.2 【代码】泛型应用在方法上
import java.util.ArrayList;
/*
* 泛型应用在方法上
* 泛型在使用时可以一次定义多个.之间使用,隔开
*/
public class Demo12 {
public static void main(String[] args) {
Dog<String> dog = new Dog<>();
//1.方法上的泛型与类上的泛型保持一致
dog.eat("吃");
//2.方法上独立使用泛型
dog.song("吃");
//3.静态方法上使用泛型
}
}
class Dog<F>{
//1.方法上的泛型与类上的泛型保持一致
public void eat(F f) {
System.out.println(f);
}
//2.方法上独立使用泛型
/*
* 注意:泛型在使用之前一定要先进行定义
* 定义的方式:在当前方法的最前面添加<泛型>
* 作用:让方法与方法内的泛型保持一致
*/
public <E> void song(E e) {
ArrayList<E> arrayList = new ArrayList<>();
System.out.println(e);
}
//3.静态方法上使用泛型
/*
* 必须独立使用
* 方式:在static 后面定义泛型 <泛型>
*/
public static <W> void show(W w) {
}
}
10.3.3 【代码】泛型应用在接口上
/*
* 泛型应用在接口上
* 我们主要研究的是实现接口的子类上的泛型是如何使用的
*/
public class Demo13 {
public static void main(String[] args) {
//1.子类上的泛型与接口上的一致
Pig<String> pig = new Pig<>();
pig.show("哈哈");
//2.接口上使用泛型,子类上不用泛型
Bird bird = new Bird();
bird.show("haha");
Class<?> class1 = bird.getClass();
}
}
interface Inte<E>{
public void show(E e);
}
//1.子类上的泛型与接口上的一致
/* 类上的泛型确定了,接口上的泛型就确定了,方法上的泛型就确定了
*/
class Pig<E> implements Inte<E>{
@Override
public void show(E e) {
System.out.println(e);
}
}
//2.接口上使用泛型,子类上不用泛型
/*在实现的接口位置必须指定一个具体的泛型
*
* 方法使用泛型的情况:
* 1.如果是重写的方法,泛型与接口一致
* 2.如果是子类自己的方法,可以与接口一致,也可以有自己的泛型
*/
class Bird implements Inte<String>{
public void show(String e) {};
}
10.4 【样例】
10.5 限制上限、限制下限
10.5.1 概述
限制上限:<? extends E>:限制的是整个的<>可以取的泛型类型的上限是E,<>中可以取的类型是E及E的子类
限制下限:<? super E>::限制的是整个的<>可以取的泛型类型的下限是E,<>中可以取的类型是E及E的父类
?:通配符,可以表示一种或几种数据类型
10.5.2 【代码】限制上限
import java.util.ArrayList;
import java.util.Collection;
public class Demo14
{
public static void main(String[] args) {
//
ArrayList<Student2> list1 = new ArrayList<>();
list1.add(new Student2("bingbing", 1));
//可以传参:因为Student2是Person1的子类,可以实现遍历
bianli(list1);
ArrayList<Teacher> list2 = new ArrayList<>();
list2.add(new Teacher("bingbing", 1));
//可以传参:因为Teacher1是Person1的子类,可以实现遍历
bianli(list2);
ArrayList<Person4> list3 = new ArrayList<>();
list3.add(new Person4("bingbing", 1));
//可以传参
bianli(list3);
ArrayList<Object> list4 = new ArrayList<>();
list4.add(new Object());
//可以传参:因为Object是Person1的父类,不可以实现遍历
//bianli(list4);
}
public static void bianli(Collection<? extends Person4> e){
System.out.println("遍历了");
}
}
class Person4{
String name;
int age;
public Person4() {
super();
// TODO Auto-generated constructor stub
}
public Person4(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person4 [name=" + name + ", age=" + age + "]";
}
}
class Teacher extends Person4{
public Teacher(String name, int age) {
super(name, age);
}
}
class Student2 extends Person4 {
public Student2(String name, int age) {
super(name, age);
}
}
10.5.3 【代码】限制下限
import java.util.Comparator;
import java.util.TreeSet;
public class Demo15 {
public static void main(String[] args) {
//限制下限 <? super E>
//TreeSet(Comparator<? super E> comparator) :这里的E跟TreeSet后面的泛型类型一致,所以现在E应该表示的Student3
//创建Student3类的比较器对象
ComWithStu comWithStu = new ComWithStu();
//创建Teacher1类的比较器对象
ComWithTea comWithTea = new ComWithTea();
//创建Person1类的比较器对象
ComWithPerson1 comWithPerson = new ComWithPerson1();
//创建GoodStudent类的比较器对象
ComWithGood comWithGood = new ComWithGood();
TreeSet<Student3> set = new TreeSet<>(comWithStu);//因为这里限制的是Student3及他的父类
//TreeSet<Student3> set = new TreeSet<>(comWithTea);//不可以使用,因为Teacher2类与Student3类没有关系
//TreeSet<Student3> set = new TreeSet<>(comWithPerson);//可以 ,因为Person3类是Student3类的父类
//TreeSet<Student3> set = new TreeSet<>(comWithGood);//不可以,因为GoodStudent类是Student3类的子类
set.add(new Student3("bingbing"));
set.add(new Student3("bingbing1"));
set.add(new Student3("bingbing2"));
}
}
//创建Student3类的比较器
class ComWithStu implements Comparator<Student3>{
public int compare(Student3 o1, Student3 o2) {
return o1.name.compareTo(o2.name);
}
}
//创建Teacher2类的比较器
class ComWithTea implements Comparator<Teacher2>{
public int compare(Teacher2 o1, Teacher2 o2) {
return 0;
}
}
//创建Person2类的比较器
class ComWithPerson1 implements Comparator<Person3>{
@Override
public int compare(Person3 o1, Person3 o2) {
// TODO Auto-generated method stub
return 0;
}
}
//创建GoodStudent类的比较器
class ComWithGood implements Comparator<GoodStudent>{
public int compare(GoodStudent o1, GoodStudent o2) {
return 0;
}
}
class Person3{
String name;
public Person3(String name) {
super();
this.name = name;
}
public String toString() {
return "Person3 [name=" + name + "]";
}
}
class Teacher2 extends Person3{
public Teacher2(String name) {
super(name);
}
}
class Student3 extends Person3{
public Student3(String name) {
super(name);
}
}
class GoodStudent extends Student3{
public GoodStudent(String name) {
super(name);
}
}
10.5.4 其它