目录
2.Lambda表达式
Lambda表达式能够代替实现匿名内部类中的抽象方法的方法体,就相当于一个匿名方法。其主要作用就是代替匿名内部类的烦琐语法。Lambda主要有三部分组成:
- 形参列表。形参列表允许省略形参类型,若列表中只有一个形参,圆括号同样也可以省略。
- 箭头(->)。
- 代码块。若只有一条语句,可以省略花括号。代码块中只有一条return语句,return同样可以省略。Lambda表达式需要返回值,若代码块中是仅有一条需要放回值的语句,Lambda表达式会自动返回这条语句的值。
Lambda表达式的类型,也被称为”目标类型(target type)“,Lambda表达式的目标类型必须是”函数式接口(functional interface)“。函数式接口代表只包含一个抽象方法的接口。函数接口可以有多个默认方法、类方法,但只能声明一个抽象方法。
Lambda表达式支持一些方法引用和构造器引用:
- 引用类方法:
(a,b,...)->类名.类方法(a,b,...)
- 引用特定对象的实例方法:
(a,b,...)->特定对象.实例方法(a,b,...)
- 引用某类对象的实例方法:
(a,b,...)->a.实例方法(b,...)
- 引用构造器:
(a,b,...)->new 类名(a,b,...)
Lambda表达式与匿名内部类的异同:
同:
- 两者都可以直接访问”effectively final“的局部变量,以及外部类的成员变量(包括实例变量和类变量)
- 两者生成的对象都一样,都可以直接调用从接口中继承的默认方法
异:
- Lambda表达式只能为函数式接口创建实例。匿名内部类却能为任意接口创建实例
- 匿名内部类还能为抽象类及不同类创建实例,但Lambda表达式不行
- 匿名内部类在实现抽象方法的时候允许调用接口中的默认方法,但Lamba表达式不允许
3.Java集合
Java的结合类主要是由 Collection 和 Map 这两个接口派生而来的,也就说 Collection 和 Map 是Java集合框架的跟接口。
下图为Java集合的基本框架:
上面的图看不看的懂先不重要,因为我也没怎么看懂,只是拿来增加b格,主要看下面的。
Java集合中的实现类有很多,但常用的是HashSet、TreeSet、ArrayDeque、LinkedList、HashMap 和 TreeMap 等。
Collection集合
- 是单例集合的顶层接口,表示一组对象,这些对象也被称为Collection的元素
- JDK不提供此接口的任何直接实现,它提供了更为具体的子接口实现(如Set、List)
例:
public class CollectionDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
//添加元素
c.add("Hello");
c.add("this");
c.add("World");
//输出
System.out.println(c);
}
}
Collection的常用方法:
集合的两种遍历方式:
- 使用迭代器Iterator
- 使用Lambda表达式遍历Iterator
- foreach循环遍历
例:
public class CollectionDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
//添加元素
c.add("Hello");
c.add("this");
c.add("World");
//使用迭代器遍历
Iterator<String> it1 = c.iterator();
while(it1.hasNext()) {
System.out.println(it1.next());
}
System.out.println("------------");
//使用Lambda表达式遍历Iterator
Iterator<String> it2 = c.iterator();
it2.forEachRemaining((String str)-> System.out.println(str));
System.out.println("------------");
//foreach循环遍历
for(String ss : c) {
System.out.println(ss);
}
}
}
List集合
有序集合(也称序列),用户可以精准控制列表中的每一个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
特点:
- 有序:存储和取出的元素顺序一致
- 元素可重复
List集合的特有常用方法:
list的集合基本使用:
public class ListDemo {
public static void main(String[] args) {
List<String> l = new ArrayList<>();
//添加元素
l.add("Hello");
l.add("this");
l.add("World");
l.add("Hello");
//使用迭代器遍历输出
Iterator<String> it = l.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}
在使用迭代器Iterator对List集合进行遍历时,不要增删集合中的元素。若不得不修改,则因使用ListIterator迭代器。
List集合的常用子类:
- ArrayList:底层数据结构为数组,查询快,增删慢
- LinkedList:底层数据结构为链表,查询慢,增删快
ListIterator迭代器
又称列表迭代器,是List集合特有的迭代器。允许程序员沿任一方向遍历列表,并后去当前表中迭代器的位置。
常用方法:
Set集合
不包含重复元素的集合,因为没有带索引的方法,故不可使用普通的for循环进行遍历。
set集合的基本操作:
public class SetDemo {
public static void main(String[] args) {
Set<String> s = new HashSet<>();
//添加元素
s.add("Hello");
s.add("this");
s.add("World");
//不允许有重复元素
s.add("Hello");
//增强for循环遍历输出
for(String str : s) {
System.out.println(str);
}
}
}
HashSet集合
- 底层数据结构为哈希表
- 对集合的迭代顺序不作任何保证,也即不保证存储和取出的元素顺序一致
- 因为是Set集合的子类集合,同样有着Set集合的特点
LinkedHashSet集合
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序
- 由哈希表保证元素唯一
TreeSet集合
-
元素有序(按照一定规则排序排序),具体的排序方式由构造方法决定
TreeSet():根据元素的自然排序进行排序(升序)
TreeSet(Comparator comparator):根据指定的比较器进行排序
-
有着Set集合的基本特点
Map集合
此集合用于保存具有映射关系的数据。集合中保存着两组值,一组为键值(key),一组为值(value),每组key值与value值间都存在固定的映射关系,可以通过key值快速查找到对应的vale值。集合中键值是唯一的,但是一个键值可以映射多个值。
常用方法:
两种遍历输出方式:
- 通过键值集合再遍历
- 获取所有键值对的对象集合后再遍历
例:
public class MapDemo {
public static void main(String[] args) {
Map<String, String> m = new HashMap<>();
//添加元素
m.put("1001", "张三");
m.put("1002", "李四");
m.put("1003", "王五");
//通过键值集合再遍历
Set<String> keySet = m.keySet();
for(String key : keySet) {
String value = m.get(key);
System.out.println(key + " - " + value);
}
//获取所有键值对的对象集合后再遍历
Set<Map.Entry<String, String>> entrySet = m.entrySet();
for(Map.Entry<String, String> mm : entrySet) {
String key = mm.getKey();
String value = mm.getValue();
System.out.println(key + " - " + value);
}
}
}
4.异常
在Java语言中,将程序执行过程中发生的不正常情况才称为“异常”。
PS:开发过程中的语法错误和逻辑错误不是异常。
异常事件可分为两类:
- Error:JVM无法解决的严重问题。如:JVM系统内部错误、资源耗尽等情况。一般不编写针对性代码进行处理。
- Exception:其他因编程错误后偶然的外在因素导致的一般性问题。如:空指针访问、试图读取不存在文件、网络链接中断、数组越界等。可以使用针对性代码进行处理。
下图为异常类的继承体系:
PS:蓝色标注的为非受检(unchecked)异常
异常处理
处理机制一:
捕获处理(try - catch - finally)
try {
//可能会出现异常的代码块
}
catch(异常类型1) {
//异常处理代码块
}
catch(异常类型2) {
//异常处理代码块
}
...
catch(异常类型) {
//异常处理代码块
}
finally {
/*
* 一定会执行的代码
* 一般为关闭物理链接的处理命令
*/
}
- try模块中捕获的异常,在catch中的运行逻辑与switch分支语句相似,只要被其中之一获取,之后的catch就不会执行。
- 因为catch对异常的获取逻辑,所以异常处理时应遵循”先处理小异常,再处理大异常“的准则。
处理机制二:
抛出处理(throws)
[修饰符] class 类名 throws 异常类型 {
//类定义
}
- 此处理方式只是将异常抛给了调用它的模块,实际异常并未得到解决,应在之后的被抛异常的模块中对异常进行一定的处理。
- 异常对象在产生并被抛出后,其之后的代码就不会在被执行。
手动抛出异常
throw new 异常类型();
自定义异常
- 继承现有异常结构(RuntimeException、Exception)
- 提供全局常量serialVersionUID
- 提供构造器对所继承的父类的构造器进行调用
例:
public class MyException extends Exception {
public MyException() {}
public MyException(String msg) {
super(msg);
}
}
5.IO流
- IO:输入/输出(Input/Output)
- 流:流是一种抽象的概念,是对数据传输的总称。也即数据在设备间的传输称为流,其本质为数据传输
- IO流就是用来处理设备间数据传输问题的,如:文件上传、文件复制、文件下载
IO流的分类
字节流写入时的换行问题:
- windows:\r\n
- linux:\n
- mac:\r
字节缓冲流:
- BufferedOutputStream:该类实现缓冲输出流。通过设置这样的流,可以直接向底层输入流写入字节,避免了多次底层系统的调用。
- BufferedInputStream:创建此流将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充。
- 字节缓冲流仅仅提供了缓冲区,真正的读写数据还得依靠基本的字节流对象进行操作。