Java SE 基础(秋招抢救版)(下-进阶篇)

七、集合

简介

JAVA中的集合是一个名词,数据的一种容器,用于容纳数据。
JAVA集合框架中就包含了对不确定个数的数据处理的集合类。
#总结:对不确定的有关系的数据进行相同的逻辑处理的场合,使用集合是一个不错的选择
根据数据的不同设立不同集合规则,JAVA集合分为两大体系:

  • 单一数据体系:Collection接口定义了相关的规则
  • 成对出现的数据体系:Collection接口定义了相关的规则(两个数据有关系,可以通过第一个数据关联到第二个数据)//也称之为键值对数据
常用接口和类
Collection接口:

常用的子接口:
List:按照插入保存数据,数据是可重复的
- 具体实现类:ArrayList,LinkedList
Set:集,无序保存,数据不能重复
- 具体实现类:HashSet
Queue:队列
- 具体实现类:ArrayBlockingQueue

Map接口:

具体实现类:HashMap,Hashtable

ArrayList

List:列表,清单
按照数据插入顺序进行存储
Array:数组,阵列

基本操作

ArrayList list = new ArrayList();
1.不需要传递构造参数,直接new就可以,底层数组为空数组。(用到时候再放)
2.构造参数需要传递一个int类型的值,用于设定底层数组的长度。(马上放数据)
3.构造参数需要传递一个Collection集合类型的值,用于将其他集合中的数据放置在当前集合中。(Collection c)

增加数据
List.add(“示例”);或者整型数字也可以
ArrayList list = new ArrayList(3);
假如已经加了三条数据,再来一条依然能放进去,假如是数组的话就会报错了。当放第四条数据的时候,ArrayList中会产生新的更大的数组(扩容),然后来引用第四条数据,旧的已经不再使用。
访问集合中数据

  • 获取条数:list.size()
  • 获取指定位置数据:list.get(0)获取索引0的
  • 遍历集合数据:for(int i=0;i<list.size();i++) { sout(list.get(i)); }
  • 如果循环遍历集合数据时,不关心数据的位置,那么可以采用特殊的for循环:for(Object obj:list) { sout{obj}; }格式:for(循环对象:集合)
    修改数据
    list.set(0,修改的新数据)//修改索引为0的数据
    删除数据
    list.remove(0)删除索引为0的数据
    Object obj=list.remove(0),输出obj就是删除的值
常用方法
  • add(0,“zhangsan”)方法可以传递2个参数的,第一个参数表示索引,第二个表示数据。假如说原来的位置0已经有东西了,那么就从该位置开始替换为新数据,旧数据集体后移。
  • addAll()示例:
ArrayList list = new ArrayList();
ArrayList list222 = new ArrayList();
list.add("zhangsan");
list.add("zhangsan2");
list222.addAll(list);

直接把list的数据都放到list222中了。

  • clear()数据全部清空
  • isEmpty()判断集合数据是否为空。
  • removeAll()删除指定集合中数据,用法跟addAll()一样,A.removeAll(B)就相当于把A中B的元素清除
  • contains()判断是否包含
  • indexOf(数据)判断该数据在集合的第一个位置,如果没有返回-1
  • lastIndexOf(数据)判断该数据在集合的最后一个位置
  • xxx.toArray()集合变数组
  • xxx.clone()复制创建一个新的集合,后加.var克隆一个新的对象(通用类型)
LinkedList

链表

基本操作

获取数据
list.get(0)//获取索引0的
list.getFirst()//获取第一个
list.getLast()//获取最后一个
增加数据
list.add(“zhangsan”)
list.addFirst(“zhangsan”)
list.add(1,“zhangsan”)在原先索引1的位置插入

LinkedList list=new LinkedList<>();  
list.add("zhangsan");  
System.out.println(list);  
System.out.println(list.getFirst());  
System.out.println(list.getLast());  
list.add("zhangsan1");  
System.out.println(list);  
list.addFirst("zhangsan2");  
System.out.println(list);

运行结果:
[zhangsan]
zhangsan
zhangsan
[zhangsan, zhangsan1]
[zhangsan2, zhangsan, zhangsan1]
遍历数据

  • 获取条数:list.size()
  • 获取指定位置数据:list.get(0)获取索引0的
  • 遍历集合数据:for(int i=0;i<list.size();i++) { sout(list.get(i)); }
  • 如果循环遍历集合数据时,不关心数据的位置,那么可以采用特殊的for循环:for(Object obj:list) { sout{obj}; }格式:for(循环对象:集合)
    修改数据
    list.set(0,修改的新数据)//修改索引为0的数据
    删除数据
    list.remove(0)删除索引为0的数据
    list.remove()删除第一个
    list.removeAll()与上面ArrayList中用法一样
    list.removeFirst()删除第一个
    list.removeLast()删除最后一个
    Object obj=list.remove(0),输出obj就是删除的值
常用方法
  • clear()数据全部清空
  • isEmpty()判断集合数据是否为空。
  • removeAll()删除指定集合中数据,用法跟addAll()一样,A.removeAll(B)就相当于把A中B的元素清除
  • contains()判断是否包含
  • indexOf(数据)判断该数据在集合的第一个位置,如果没有返回-1
  • lastIndexOf(数据)判断该数据在集合的最后一个位置
  • xxx.toArray()集合变数组
  • xxx.clone()复制创建一个新的集合,后加.var克隆一个新的对象(通用类型)
  • list.push(“aaa”)//添加数据,数据直接添加到第一个
  • list.pop()//删除第一个数据
泛型
介绍

泛型语法:ArrayList<P> list=new ArrayList<P>();
表示存放到集合的是P类型的,添加的类型不满足要求,就会报错。

import java.util.ArrayList;  
  
public class Chap {  
public static void main(String[] args) {  
ArrayList list=new ArrayList();  
P p=new P();  
U u=new U();  
list.add(p);  
list.add(u);  
Object o = list.get(0);  
o.s();//运行会报错,多态限制使用场景  
}  
}  
class P{ 
public void s(){}
}  
class U{}

集合仅是一个容器,没有约束存储数据类型,获取对象时就返回了一个通用类型Object。这样对象o由于多态的限制无法使用P中的方法,因此可以进行强制类型转换来使用(P m=§o)
假如引入泛型,就不用这么麻烦,直接声明集合中只能存放这个类型的对象,取出时就可直接使用这个类型的方法。

基本使用

泛型的声明:interface接口<T>和class类<k,v>

比较器

list.sort(传入一个比较器的对象);

HashSet

放数据可以重复,但是存储不会重复。
HashSet set=new HashSet();
set.remove(“wangwu”)
set.add(“zhangsan”)
无法查询(只能遍历得到)
无法修改(只能先删除后添加)

常用方法

与之前的一样

Queue

ArrayBlockingQueue queue=new ArrayBlockingQueue(3);
queue.add(“zhangsan”)
queue.add(“zhangsan1”)
queue.add(“zhangsan2”)
queue.add(“zhangsan3”)//que已满报错
que.put(“zhangsan”);
que.put(“zhangsan”);
que.put(“zhangsan”);
que.put(“zhangsan”);//阻塞,代码没继续进行
queue.offer(“zhangsan”)//返回bool类型数据
queue.offer(“zhangsan”)
queue.offer(“zhangsan”)
queue.offer(“zhangsan”)//已经满了返回false
queue.pull()//取出第一个
queue.pull()
queue.pull()
queue.pull()//取不出来只能取出[ ]
queue.take()//取出第一个
queue.take()
queue.take()
queue.take()//代码不会继续运行,阻塞

HashMap

映射
HashMap map=new HashMap();//可放参数表示大小
map.put(“a”,“1”)
map.put(“b”,“2”)
map.put(“c”,“3”)
数据存储无序,数据存储无重复
K值相同后来的会把旧的覆盖掉
put也可以修改数据,返回的就是修改的值
查询:
map.get(“a”);
消除数据:
remove(“b”)

常用方法

底层:单项链表+数组
添加数据:
map.put(“d”,“3”);
Object o=map.put(“d”,“4”);
System.out.println(o);//结果是3,修改返回的是旧的值
map.putIfAbsent(“b”,“2”)
map.putIfAbsent(“b”,“3”)//b已经有数据,就不放入了
修改数据:
map.replace(“b”,“3”).//修改为3
当b没有时,就不会添加数据
清空:
map.clear();
判断:
map.containsKey(“b”)判断是否有b
map.containsValue(“1”)判断是否有1这个值
Collection c=map.values()取出所有值
map.entrySet();得到键值对
map.remove(“b”)//删除
map.remove(“b”,“1”)//也能删除
map.remove(“b”,“10086”)//这个特定键值对的不存在,所以不会删除
循环遍历一旦启动,中间无法删除数据,但可以修改数据,尽量使用迭代器。

keySet()返回 hashMap 中所有 key 组成的集合视图。

Hashtable

Hashtable t=new Hashtable()
put
get
remove都有

与HashMap的不同
  • HashMap的pv值都可以是null,数据定位采用Hash算法,Hashtable用的Hashcode
  • HM性能较高,HT性能较低
  • 底层结构容量不同,HM(16)HT(11)
  • 继承父类不同
迭代器

iterator
迭代器接口定义了几个方法,最常用的是以下三个:

  • next() - 返回迭代器的下一个元素,并将迭代器的指针移到下一个位置。

  • hasNext() - 用于判断集合中是否还有下一个元素可以访问。

  • remove() - 从集合中删除迭代器最后访问的元素(可选操作)。
    // 获取迭代器
    ArrayList<String> sites = new ArrayList<String>();
    Iterator<String> it = sites.iterator();
    hasNext()判断是否有下一条数据
    // 输出集合中的所有元素
    while(it.hasNext()) {
    System.out.println(it.next());
    remove只能对当前数据删除,不能对其他数据删除

工具类
package Chap06;  
  
import java.util.Arrays;  
import java.util.List;  
  
public class TOOL {  
public static void main(String[] args) {  
int[]i={1,2,3,4,5,6,7,8,9,10};  
int[]i2={1,2,3,4,5,6,7,8,9,10};  
System.out.println(Arrays.toString(i));  
System.out.println(i);  
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);  
System.out.println(list);  
Arrays.sort(i);  
System.out.println(Arrays.binarySearch(i, 9));//返回值是排序后的数组中,9所在的位置,从0开始  
System.out.println(i);  
System.out.println(Arrays.equals(i, i2));//位置相同的地方都相等返回true,假如乱序不同返回false  
System.out.println(Arrays.equals(i,0,5,i2,0,5));//0,5表示从第0位开始,到第5位结束,所以是前6位,从第0位开始,到第5位结束,所以是前6位  
}  
}

八、IO

文件流
package CHAP08;  
import java.io.*;  
  
public class ioo {  
public static void main(String[] args) {  
String filepath="E:\\Coding\\Java-Project\\untitled1\\data\\nfiee.txt";  
File file=new File(filepath);  
System.out.println(file);//打印出路径  
//文件对象的操作  
System.out.println(file.isFile());//判断当前文件对象是否为文件,假如把路径改到文件夹,就是false  
file.isDirectory();//判断是否为文件夹  
file.exists();//判断文件对象是否存在关联  
//file.mkdirs();//创建多级文件目录  
try {  
file.createNewFile(); // 保留原行,但添加异常处理  
} catch (IOException e) {  
e.printStackTrace();  
}//创建新文件   
}  
}
文件复制
package CHAP08;  
import java.io.*;  
public class M08 {  
public static void main(String[] args) {  
File file=new File("E:\\Coding\\Java-Project\\untitled1\\data\\nfiee.txt");  
File file2=new File("E:\\Coding\\Java-Project\\untitled1\\data\\nfiee.txt.copy");//自动生成文件  
FileInputStream fis=null;//为什么要设置为NULL?避免编译错误:如果变量未被初始化(即使声明时未赋值),在 try 块外直接使用会导致编译错误(可能未初始化)。  
FileOutputStream fos=null;  
try{ //文件输入流,管道对象  
fis=new FileInputStream(file);  
fos = new FileOutputStream(file2);  
//打开阀门,流转数据(输入)  
int data = fis.read();  
//输出  
fos.write(data);  
data = fis.read();  
fos.write(data);  
data = fis.read();  
fos.write(data);  
data = fis.read();  
fos.write(data);  
//如果文件数据读取完毕,在读取读取结果为-1  
while(data!=-1){//为了避免上述重复,可以直接循环  
fos.write(data);  
data = fis.read();  
}  
  
}  
catch(IOException e){  
e.printStackTrace();  
}finally{  
if(fis!=null){try{fis.close();}  
catch(IOException e){e.printStackTrace();  
}  
}  
if (fos!=null){  
try{  
fos.close();  
}  
catch(IOException e){  
e.printStackTrace();  
}  
}  
}    
}  
}

如果不想要每次复制都只能复制过去一个字符的话,可以采用缓冲流Buffer

字符串

可将字符串转换为字节数组,然后将数组中的每一个字节写到文件中

package Chap06;  
  
import java.io.*;  
public class M08 {  
public static void main(String[] args) {  
File file=new File("E:\\Coding\\Java-Project\\untitled1\\data\\nfiee.txt");  
File file2=new File("E:\\Coding\\Java-Project\\untitled1\\data\\nfiee.txt.copy");//自动生成文件  
//FileInputStream fis=null;//为什么要设置为NULL?避免编译错误:如果变量未被初始化(即使声明时未赋值),在 try 块外直接使用会导致编译错误(可能未初始化)。  
//FileOutputStream fos=null;  
BufferedReader fis=null;  
PrintWriter fos=null;  
try{ //文件输入流,管道对象  
fis=new BufferedReader(new FileReader(file));  
fos = new PrintWriter(file2);  
//打开阀门,流转数据(输入)  
// int data = fis.read();  
//输出  
// fos.write(data);  
// data = fis.read();  
// fos.write(data);  
// data = fis.read();  
// fos.write(data);  
// data = fis.read();  
// fos.write(data);  
String data=null;  
//如果文件数据读取完毕,在读取读取结果为-1  
while((data= fis.readLine()) != null){//为了避免上述重复,可以直接循环  
//fos.write(data);  
//data = fis.read();  
fos.println(data);  
}  
//刷写数据  
fos.flush();//把缓冲区的数据强制全部输出  
}  
catch(IOException e){  
e.printStackTrace();  
}finally{  
if(fis!=null){try{fis.close();}  
catch(IOException e){e.printStackTrace();  
}  
}  
if (fos!=null){  
fos.close();  
}  
}  
  
  
}  
}

这样会直接输出字符串而不是ASCII码

序列化(把对象变成字节)

反序列化:字节变为对象

package Chap04;  
import java.io.*;  
public class M08 {  
//构建了一个分层管道系统,允许将Java对象通过以下流程写入文件: 对象 → 智能处理站(序列化为字节流) → 物理管道 → 文件  
public static void main(String[] args) {  
File file=new File("E:\\Coding\\Java-Project\\untitled1\\data\\nfie.txt");  
//对象输出流  
ObjectOutputStream fis=null;  
FileOutputStream fos=null;  
try{ //文件输入流,管道对象  
fos=new FileOutputStream(file);  
fis = new ObjectOutputStream(fos);//顺序不可变,ObjectOutputStream装饰类必须依附于一个OutputStream  
User user=new User();  
fis.writeObject(user);  
fis.flush();  
}  
catch(IOException e){  
e.printStackTrace();  
}finally{  
if(fis!=null){try{fis.close();}  
catch(IOException e){e.printStackTrace();  
}  
}  
  
}  
  
  
}  
}  
class User implements Serializable{  
  
  
}

反序列化就是改成ObjectInputStream,FileInputStream即可
然后Object o=fis.readObject();即可

九、线程

进程

定义:自己写的程序就是一个进程,它的名字就是执行的类的名字。

线程

定义:java程序运行时候默认就会产生一个进程,这个进程会有一个主线程,代码都在主线程中执行。

创建线程
package Chap04;  
  
public class TT {  
public static void main(String[] args) {  
  
myThread t=new myThread();  
t.start();  
System.out.println("MyThread"+Thread.currentThread().getName());  
}  
}  
class myThread extends Thread{  
//重写运行指令  ctrl+o
  
@Override  
public void run() {  
System.out.println("MyThread"+Thread.currentThread().getName());  
}  
}

运行结果是:
main
MyThread
两条县城互不干扰,没有必然先后关系,但是新的线程要准备,因此启动时候会慢于main线程

生命周期

线程的生命周期主要包括以下几个状态:
NEW:        线程新建状态
RUNNABLE:     就绪状态 (可运行状态)
RUNNING:   运行状态 (等待状态)
BLOCKED:     堵塞状态
TERMINTED:    终止状态
runnable可以转换为除了首尾的其他状态

线程执行方式

串行执行,并发执行

  • 先来看并发执行:如下列代码,除了main线程,其他两个线程启动顺序不一定,谁先抢到CPU执行权就算谁的
package Chap04;  
  
public class TT {  
public static void main(String[] args) {  
  
myThread t1=new myThread();  
myThread2 t2=new myThread2();  
t1.start();  
t2.start();  
System.out.println("main执行完毕");  
}  
}  
class myThread extends Thread{  
//重写运行指令  
  
@Override  
public void run() {  
System.out.println("MyThread"+Thread.currentThread().getName());  
}  
}  
class myThread2 extends Thread{  
//重写运行指令  
  
@Override  
public void run() {  
System.out.println("MyThread2"+Thread.currentThread().getName());  
}  
}
  • 串行
package Chap04;  
  
public class TT {  
public static void main(String[] args) throws InterruptedException {  
  
myThread t1=new myThread();  
myThread2 t2=new myThread2();  
t1.start();  
t1.join();//相当于阻塞,等待t1执行完毕才会执行下一线程  
t2.start();  
t2.join();  
System.out.println("main执行完毕");  
}  
}  
class myThread extends Thread{  
//重写运行指令  
  
@Override  
public void run() {  
System.out.println("MyThread"+Thread.currentThread().getName());  
}  
}  
class myThread2 extends Thread{  
//重写运行指令  
  
@Override  
public void run() {  
System.out.println("MyThread2"+Thread.currentThread().getName());  
}  
}
线程休眠
package Chap04;  
  
public class TTTT {  
public static void main(String[] args) throws InterruptedException {  
Thread.sleep(1000);//休眠一秒钟  
System.out.println("Hello");  
while(true){  
Thread.sleep(1000);//休眠一秒钟  
System.out.println("Hello");//每一秒钟打印一个  
  
}  
}  
}
工作
package Chap04;  
  
public class RRRR {  
public static void main(String[] args) {  
Thread3 t3 = new Thread3();  
t3.start();  
Thread4 t4 = new Thread4();  
t4.start();  
System.out.println("main执行完毕");  
  
  
}  
}  
class Thread3 extends Thread {  
public void run() {  
  
System.out.println("Thread3: " );  
  
}  
}  
class Thread4 extends Thread {  
public void run() {  
  
System.out.println("Thread4: " );  
  
}  
}

结果:
Thread3:
main执行完毕
Thread4:
主线程在启动子线程后会继续执行后续代码(System.out.println(“main执行完毕”)),而子线程的执行由JVM调度器决定。由于线程调度的不确定性,t3的run()方法可能在主线程打印"main执行完毕"前被调度执行

线程池
同步

关键字synchronized,可修饰方法和代码块
方法:public synchronized void test
代码块:synchronized(用于同步的对象){处理逻辑 }

package Chap04;  
  
public class Tongbu {  
public static void main(String[] args) {  
NUMBER number=new NUMBER();  
KeHu kehu=new KeHu(number);  
kehu.start();  
Bank bank=new Bank(number);  
bank.start();  
  
  
}  
}  
class NUMBER{}  
class KeHu extends Thread{  
private NUMBER number;  
public KeHu(NUMBER number){  
this.number=number;  
}  
public void run(){  
synchronized (number){  
System.out.println("银行没开门我先等一会");  
try {  
number.wait(20000);  
} catch (InterruptedException e) {  
e.printStackTrace();  
}  
System.out.println("银行开门了,我可以办业务了");  
}}  
  
}  
class Bank extends Thread{  
private NUMBER number;  
public Bank(NUMBER number){  
this.number=number;  
}  
public void run() {  
synchronized (number) {  
System.out.println("银行开门了");  
try {  
Thread.sleep(10000);  
} catch (InterruptedException e) {  
e.printStackTrace();  
}  
number.notify();  
}  
}  
  
  
}
wait和sleep

wait:等待(成员方法) sleep:休眠(静态方法)
使用方法
wait:只能使用在同步代码中。
sleep:可以在任意地方使用。
阻塞时间
w:超时时间
s:休眠时间(不会发生错误)
同步处理:
w:如果执行,那么其他线程有机会执行当前同步操作
s:如果执行,那么其他线程没有机会执行当前同步操作

十、反射

java中的类主要分为三种
核心类库中的(String,Object):加载类时,采用操作系统平台语言实现
JVM软件平台开发商
自己写的类
类加载器也有三种
BootClassLoader:启动类加载器
PlatformClassLoader:平台类加载器
AppClassLoader:应用类加载器
加载顺序
核心类库>平台类库>自己类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值