javaSE高级编程(集合、IO、网络)的学习笔记(第二部分)

2.1 集合体系
2.1.1 集合介绍
1、集合本身就是一个对象,用于存取其它对象,只能存取引用类型(基本数据类型会自动装箱)。
2、单列集合Collection(Set、List)的顶层父接口是Iterable
3、Iterator接口:迭代器接口,能够对实现了Iterable接口的集合进行迭代。

2.1.2 List集合
一、list集合的遍历(arrayList和linkedList)
1、list索引遍历
for (int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
2、增强for循环遍历
for (Object obj: list) {
System.out.println(obj);
}
3、迭代器遍历
Iterator iterator=list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
4、jdk8可以用Lambda表示遍历
//1.使用Lambda表示遍历
list.forEach(new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});
//2.使用Lambda表示遍历
list.forEach((Object ob)->{
System.out.println(ob);
});
//3.使用Lambda表示遍历
list.forEach((Object ob)->System.out.println(ob));
//4.使用Lambda表示遍历
list.forEach(System.out::println);
二、list集合的注意事项
1、在用迭代器遍历List集合时,不能添加元素,否则会出现“并发异常”,可以用索引遍历添加,也可以用ListIterator遍历添加。

三、LinkedList和ArrayList比较
LinkedList类:底层实现是双向链表;该集合做元素的增加和删除比较快,但是做元素的查询和修改比较慢;ArrayList集合由于底层实现是数组,所以增删较慢,查询和修改较快。
2.1.3 Set 集合
一:HashSet集合的特点
1、set 集合是无序的,允许为null,不能重复。
2、HashSet集合如何来判断元素不可重复?
答:根据哈希值来判断添加的元素是否相同,如果哈希值相同,则继续通过equals方法判断;如果自己重写了hashCode方法和equals方法,则按照重写的规则来进行比较。
二:Set集合遍历(HashSet和TreeSet)
1、增强for循环
for (Object object:set){
System.out.println(object);
}
2、迭代器遍历
Iterator iterator=set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
3、Lambda表达式遍历
set.forEach(new Consumer() {
@Override
public void accept(Object o) {
System.out.println(o);
}
});
//使用Lambda表示遍历
set.forEach((Object ob)->{
System.out.println(ob);
});
//使用Lambda表示遍历
set.forEach((Object ob)->System.out.println(ob));

    set.forEach(System.out::print);

三:TreeSet集合的特点
1、TreeSet类是Set集合的实现类,底层是二叉树,无序不可重复,会对元素依据Comparable接口中compareTo方法进行比较排序。
2、TreeSet不能添加不同类型的元素,默认为第一个添加元素的类型,最好定义好泛型。
3、Comparable接口让其实现类具有自我排序性。
四:Comparable和Comparator
(1)Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序(内部排序),让需要比较的类实现该接口的 compareTo 方法被称为它的自然比较方法。
(2)Comparator强行对某个对象 collection 进行整体排序(外部排序)的比较函数,单独定义一个类实现该接口。
注意:默认升序排列
若要降序,则改为返回 -n 即可
set.sort(new Comparator() {

// @param o1 代表两个比较值中的后一个对象
// @param o2 代表两个比较值中的前一个对象
public int compare(Object o1, Object o2) {
Student stu1 = (Student) o1;
Student stu2 = (Student) o2;
int n=stu1.getAge()-stu2.getAge();
);
if (n != 0) {
System.out.println(n);
return n;
}
int w = stu1.getName().compareTo(stu2.getName());
return w;
}
});
2.1.4 Map 集合
一:Map集合的特点(HashMap和TreeMap)
1、Map集合是双列集合,集合有k,v成对出现(K - 此映射所维护的键的类型V - 映射值的类型),Map集合的特性与Set集合的特性一致,Map集合的value任意。
2、HashMap的key可以为空,TreeMap的key不能为空(排序会出现空指针异常)。
二:Map集合遍历
1、将Map集合的key转化成Set集合,遍历Set集合,然后根据key获取Map中的value。
//通过key的遍历取得Value值
Set keys=map.keySet();
Iterator iterator=keys.iterator();
while(iterator.hasNext()){
int key=(int)iterator.next();
System.out.println(key+"–>"+map.get(key));
}
2、将Map集合中的所有Value转化成Collection集合。
Collection val=map.values();
for (String str:val){
System.out.println(str);
}
3、将Map集合中的所有元素通过调用entrySet()方法转化成Set集合。该Set集合中每个元素都是Map.Entry类型,Entry表示的Map集合中的每一个键值对。
Set<Map.Entry<Integer, String>> mm = map.entrySet();
for (Map.Entry<Integer, String> m : mm) {
System.out.println(m.getKey()+":"+m.getValue());
}
4、lambda表达式遍历Map集合
map.forEach((k,v)->{
System.out.println(k+":"+v);
});
2.2 泛型
一、泛型(参数化类型)
1、Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
2、注意:类型擦除—》 泛型只在编译阶段有效,编译完成后会擦除泛型,泛型信息不会进入到运行时阶段。
3、泛型的类型参数只能是类类型,不能是基本数据类型。
二、自定义泛型类
1、泛型类
(1)泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。
注意:当有子类继承了泛型类,如果在泛型类【父类】上没有确定【指定】泛型参数的实际类型,则需要将该子类也定义为同样参数的泛型类。
语法:public class 类名{
private T t;
public void setObj(T t){
this.t=t;
}
public T getObj(){
return this.t;
}
}
2、泛型接口
(1)泛型接口的声明和非泛型接口的声明类似,除了在接口名后面添加了类型参数声明部分,泛型接口的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。
注意:当有子类实现了该泛型接口之后,如果没有指定泛型参数的实际类型,则该子类也必须定义为泛型类;
语法:public interface 接口名{
void show(T t);
}
3、泛型方法
(1)在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
(2)下面是定义泛型方法的规则:
所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前。
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
例如:成员方法(非静态)
权限修饰符 返回值类型 方法名(T t){
}
静态成员方法
权限修饰符 static 返回值类型 方法名(T t){
}
注意:静态方法中不能直接使用泛型类上的泛型参数;否则需要将该方法也定义为泛型方法。
4、类型通配符
当不能确定泛型参数传递什么类型时,可以使用<?>表示参数类型。
5、有界的类型参数
允许传递到一个类型参数的类型种类范围,例如,一个操作数字的方法可能只希望接受Number或者Number子类的实例。这就是有界类型参数的目的。
例如:public static <T extends Comparable> T maximum(T x, T y, T z){
}
4、泛型变量
(1)泛型变量不能用静态static修饰,泛型变量是引用类型的,成员变量默认初始化为null,局部泛型变量在使用前需要初始化。

三、泛型通配符
1、当不能确定泛型参数传递什么类型时,可以使用<?>表示参数类型。
2、泛型上限<? extends B>:所传递的泛型类型只能是泛型本身或者泛型的子类类型。
3、泛型下限<? super B>:所传递的泛型类型只能是泛型本身或者泛型的父类类型。
4、当集合创建对象的时候,该集合的泛型参数上有通配符,只能显示查询对象,不能有添加操作。
四、为什么使用泛型
将运行时的错误转移到编译时期,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
2.3 枚举(enmu)
一、枚举理解
1、枚举指的是java语言中一种特殊的类,但是这种类的对象个数是一定的,构造方法只能是private修饰,可以定义成员变量及成员方法。
2、自定义枚举类,关键字enum,枚举类的构造器默认私有化了,直接提供了该类的对象,并且默认是public static final修饰的,自定义枚举类enum继承了java.lang.Enum类。
3、枚举类的对象必须放在枚举类的第一行,如果枚举类中有抽象方法,则需要在枚举类的每个对象上重写此抽象方法。
4、枚举类可以实现接口,但是不能继承类(已经默认继承了Enum类)。所实现接口中的抽象方法可以在枚举类中重写抽象方法(所有枚举对象共享),也可以在枚举类的每个对象上重写此抽象方法。

2.4 反 射
一、反射理解
1、Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
2、Clas类:用来描述.class文件,Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
3、类加载机制:启动类加载器,扩展类加载器,系统类加载器,网络类加载器,自定义类加载器
4、双亲委托加载:向上委托,向下加载。
二、反射镜像获取
1、通过类或属性.class获取
2、通过对象.getClass()获取
3、通过全限定类名的字符串形式类获取Class.forName(“strName”),通过此方式获取的对象需要用Class接收,被获取的类需要含有无参构造器。
三、反射获取属性和方法
1、通过全限定类名的字符串形式类获取Class.forName(“strName”),用Class接收对象,可以通过对象.newInstance()产生类的实例,可以通过对象.get***()方法获取类的属性和方法。对于属性的操作在Field类里,对于方法的操作在Method类中。
2、get***()方法能获取public修饰的属性及方法。
3、getDeclared***()可以获取全部的属性或方法(其中declared表示已声明,只要是声明的方法,包括私有的都可以访问)
4、要想给私有属性赋值,则要设置setAccessible(true);要想访问私有方法,也要设置 .setAccessible(true),才能通过.invoke(传入调用私有方法的对象)访问私有方法。
2.5 异常
一、异常理解
1、程序编译或者运行过程中出现了错误导致程序终止,不能继续运行。
二、异常分类
1、错误:不可修复的异常,严重时会导致系统奔溃。
2、异常:可修复的错误,分为:
编译时期异常–》受查异常(在编译时期就会检查,必须处理)
运行时期异常—》非受查异常(运行时才会检查,属于程序逻辑问题,修改逻辑即可)。
三、异常处理
1、声明异常(throws):声明者将异常抛出,调用者只能继续抛出异常或者进行捕获处理,最终需要捕获处理。否则到jvm会停止程序。
2、try…catch:捕获异常可以使程序继续向下执行。
3、try…catch…finall y:finally后写必须执行的代码。
注意:只要finally中有return语句,不论try中是否含有return语句,都肯定会执行finally中的return语句,将try语句中的return的功能隐藏掉。如果try中有return语句,而finally中没有,则会先挂起try中的return语句,再执行finally语句,最后执行return语句。
4、throw:主动抛出异常,交给调用者处理。
四、自定义异常
1、自定义异常,自己定义一个异常类继承Throwable(Exception或着RunTimeException),可以通过throw主动抛出异常,交给调用者处理。
五、断言assert
1、语法:assert 布尔表达式 [:“错误表达式”];
2、java中断言默认关闭,需要自己开启;在运行条件配置中配置VM options: -ea。
2.6 线程
一、线程理解
1、进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
2、线程:进程内部的一个独立执行单元,来完成进程中的某个功能 . 一个进程可以同时并发的运行多个线程,可以理解为一个进程便相当于一个单 CPU 操作系统,而线程便是这个系统中运行的多个任务。
3、进程:有独立的内存空间,进程之间数据存放空间(堆空间和栈空间)是独立的,每个进程至少有一个线程。
4、线程:一个进程中多个线程共享堆空间,栈空间是独立的,线程消耗的资源比进程小的多。
5、Java 程序的进程里面至少包含两个线程,主进程也就是 main()方法线程,另外一个是垃圾回收机制线程。每 当使用 java 命令执行一个类时,实际上都会启动一个 JVM,每一个 JVM 实际上就是在操作系统中启动了一个进程,main方法就该进程中的一个线程,java 本身具备了垃圾的收集机制,所以在 Java 运行时至少会启动两个线程。
6、多线程是cpu快速切换计算的结果,在计算机内部某一时刻只能执行一个线程,由于切换速度过快,表面看起来一时间执行多个线程。
7、通过对多线程的使用,可以编写出非常高效的程序。不过请注意,如果你创建太多的线程,程序执行的效率实际上是降低了,而不是提升了,CPU 花费在上下文的切换的时间将多于执行程序的时间!
8、线程调度策略:抢占式调度和协同式调度
二、自定义线程
1、继承Thread类,重写父类的run()方法,线程的启动需要调用strat()方法,而不能直接调用run()方法(这样调用是普通方法的调用,不是多线程)。
2、实现Runnable接口,实现接口的run()方法,同样线程的启动需要调用strat()方法,而不能直接调用run()方法。如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。
3、实现Callable接口:Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。

三、线程的状态
1、并发:多个线程同时执行 并行:多个进程同时执行
2、学习Thread类和Object类中的方法。
3、线程的状态:

注意:线程在创建之后只能调用一次start()方法,再次调用会出现IllegalThreadStateException异常;已经消亡的方法再次调用start()也会出现此异常。
补图:
四、线程并发(安全)
1、synchronized(同步的):在并发编程中存在线程安全问题,主要原因是多线程共同操作共享数据。关键字synchronized可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时synchronized可以保证一个线程的变化可见。
2、异步指的是当多个线程同时执行时,每个线程之间没有关系。
3、同步代码块语法:synchronized (锁对象) {
}
同步锁对象:可以是java中的任意一个类的对象,拥有该对象的标志才可以执行同步代码块中的代码。注意:锁对象必须是同一个对象地址(同一把锁)。
4、同步方法synchronized:
Modifier [static] synchronized void Method(){}
(1)静态同步方法的锁对象是方法所在类的镜像(大Class对象)
(2)普通同步方法的锁对象是this(当前类的对象)
五、与线程间通信(等待唤醒机制)
1、为了调用wait()或者notify(),线程必须先获得那个对象的锁。
2、wait使线程停止运行,而notify使停止的线程继续运行。调用notify()方法一次只随机通知一个线程进行唤醒。线程A、B、C都执行wait()方法,通知线程只执行一次notify()方法;调用notifyall()方法对所有线程进行唤醒。
3、注意:wait和sleep的区别,wait可以不指定时间,wait释放锁,在同步代码中让出执行权,而sleep不释放锁,仅仅是让线程等待对应的时间。
六、死锁和线程优先级
1、死锁:由于各个线程之间相互争夺资源,都不释放资源,而使程序不能继续执行的现象。
2、嵌套使用锁,就会发生死锁。
2、线程中的优先级:优先级高的线程优先被CPU调度,被执行的可能性更高,java中的优先级有(int)类型的10个等级(1-10),优先级最高为10,所有线程的默认优先级是5,可以通过setPriority(int newPriority)方法修改优先级。
2.6 IO流和文件系统
一、文件描述
1、File类:在java语言中,File类是对文件系统的抽象描述,可以表示文件和目录。
2、File 类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变。
3、java写路径时,在不同的操作系统中,windoes分割符是“\”,因为单“\”表示转义字符,linux则正常书写。
二、IO流体系
理解:现代操作系统不允许普通的程序直接操作磁盘,输入输出是相对于内存而言,输出的数据要干什么?把内存当作一个缓冲区,写入到目标文件。
字节流 : 字节流可以操作任何数据(拷贝音频、图片文件),因为在计算机中任何数据都是以字节的形式存储的
字符流 : 字符流只能操作纯字符数据,比较方便。
1、字节流(一般带Stream)
(1)字节流分为输入流和输出流,InputStream和OutputStream是字符流最顶层的抽象类,InputStream类中的read()方法需要每个子类自己实现; OutputStream类中的write()方法需要每个子类自己实现
(2)FileInputStream和FileOutputStream是对文件的操作最基础的字节流,
(3)BufferedInputStream和BufferedOutputStream具有缓存机制字节流,可以增强程序的执行效率。
(4)Serializable序列化就是将java对象或者数据转换成字节流,便于网络传输和持久化存储,实现了给接口的类在运行时java虚拟机会给该类的每个对象分配唯一的标识。
2、字符流
(1)Reader和Writer是字符流的抽象类,里面定义了一些抽象方法和普通方法。
(2)FileReader和FileWriter是对文件的操作最基础的字符流,
(3)BufferedFileReader和BufferedFileWriter具有缓存机制字符流,可以增强程序的执行效率。
(4)PrintWriter向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法
3、字节流和字符流转换
(1)InputStreamReader和OutputStreamWriter可以实现字节流转换成字符流。
4、随机读写流
(1)、RandomAccessFile对随机访问文件的读取和写入,但只能用于读写文件,应用于多线程下的拷贝。
2.6 网络编程
一、网络
1、IP地址:网络环境用于某一主机的标识,
2、端口:为计算机中的网络应用程序分配的标识,可以找到所需用的具体软件;取值范围:0-65535,但是0-1023为操作系统保留。
二、TCP编程
1、Socket通信:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
2、ServerSocket:此类实现服务器套接字。服务器套接字等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。
三、UDP编程
1、类 DatagramSocket数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
2、类 DatagramPacket数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。
2.6 jdk8新特性
一、接口中的默认和静态方法
1、在jdk7中,接口中只存在抽象方法,但在jdk8中可以有default和static修饰的方法。
2.在Java8+版本中,如果一个类所实现的多个接口中有一模一样的默认方法或者静态方法,在该实现类中必须重写接口中一模一样的默认方法或者静态方法。
3、在接口中的静态方法只能有该接口直接调用,不能由该接口的实现类调用。
二、Lambda
1、函数式编程,是一个接口,该接口中有且仅有一个抽象方法,其它方法不限。
2、当Lambda表达式遇到序列化问题时,只能创建具体类实现序列化,不能使用Lambda表达式。
三、“::”方法引用关键字
1、引用构造器
2、引用成员方法
3、引用类(静态)方法
四、Java 8 函数式接口
1、函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
2、函数式接口可以被隐式转换为 lambda 表达式。
四、Java 8 Stream
1、用于流式计算,流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
2、中间方法:返回值是Stream接口对象的方法,可以继续调用Stream中的方法。
3、最终方法:返回值为null或者其它类型的引用,不能继续调用Stream中的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值