java下(笔记)

双列集合的特点

  1. 双列集合一次需要存一对数据,分别为键和值
  2. 键不能重复,值可以重复
  3. 键和值是一一对应的,每一个键只能找到自己对应的值
  4. 键+值这个整体我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”

Map集合常用的API

在这里插入图片描述

//1.创建Map集合的对象
Map<String, string> m = new HashMap<>();
//2.添加元素
// put方法的细节:
//添加/覆盖

//在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中
//在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。

m.put("郭靖","黄蓉");
m.put("韦小宝","沐剑屏");
m.put("尹志平","小龙女");
string value = m.put("韦小宝""双儿");
system.out.println(value);
//3.打印集合
system.out.println(m); //???

-Map集合的第一种遍历方式


//Map集合的第一种遍历方式
//1.创建Map集合的对象
Map<String,string> map = new HashMap<>();
//2.添加元素
map.put("尹志平","小龙女");
map.put("郭靖","穆念慈");
map.put("欧阳克","黄蓉");

//3.通过键找值

//3.1获取所有的键,把这些键放到一个单列集合当中
set<String> keys = map.keySet();
//3.2遍历单列集合,得到每一个键
for ( string key : keys) {
//system.out.println( key ) ;
//3.3利用map集合中的键获取对应的值
getstring value = map.get(key);
system.out.print1n(key + " =" + value);
}

-Map集合的第二种遍历方式

public class A03_MapDemo3 {
public static void main(String[ ] args) {
//Map集合的第二种遍历方式

//1.创建Map集合的对象
Map<String,string> map = new HashMap<>();
//2.添加元素
//键:人物的外号//值:人物的名宁
map.put("标枪选手","马超");
map.put("人物挂件","明世隐");
map.put("御龙骑士","尹志平");
//3.Map集合的第二种遍历方式

//通过键值对对象进行遍历

//3.1通过一个方法获取所有的键值对对象,返回一个Set集合
Set<Map.Entry<string,string>> entries = map.entrySet();
//3.2遍历entries这个集合,去得到里面的每一个键值对对象
for (Map.Entry<String,String> entry : entries) {//entry ---’“人物挂件" ,"明世稳"
//3.3 利用entry调用get方法获取键和值
string key = entry.getKey( );
string value = entry.getvalue();
system.out.print1n(key + "=" + value);

-Map集合的第三种遍历方式

//3.利用lambda表达式进行遍历
map.forEach(new BiConsumer<StringString>() {
@override
public void accept( String key,string value) {
system.out.println(key + "=" + value);
}
});

集合进阶-06-HashMap基本的使用

HashMap的特点

  1. HashMap是Map里面的一个实现类。
  2. 没有额外需要学习的特有方法,直接使用Map里面的方法就可以了。
  3. 特点都是由键决定的:无序、不重复、无索引
  4. HashMap跟HashSet底层原理是一模一样的,都是哈希表结构
    在这里插入图片描述

集合进阶-09-LinkedHashMap

在这里插入图片描述
由键决定:有序、不重复、无索引。
这里的有序指的是保证存储和取出的元素顺序一致
原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。
在这里插入图片描述

//1.创建集合
LinkedHashMap<String,Integer> lhm = new LinkedHashMap<>();
//2.添加元素
lhm.put("c",789);
lhm.put( "b",456);
lhm.put("a",123);
lhm.put( "a",111);
//3.打印集合
system.out.println( lhm);

TreeMap的基本使用和基础…

TreeMap跟TreeSet底层原理一样,都是红黑树结构的。
由键决定特性:不重复、无索引、可排序
可排序:对键进行排序。
注意:默认按照键的从小到大进行排序,也可以自己规定键的排序规则
代码书写两种排序规则
实现Comparable接口,指定比较规则。
创建集合时传递Comparator比较器对象,指定比较规则。

Integer Double默认情况下都是按照升序排列的
String按照字母再ASCII码表中对应的数字升序进行排列

源码跳过

可变参数

Java 中使用省略号(…)来声明可变参数

可变参数的小细节:
1.在方法的形参中最多只能写一个可变参数可变参数,理解为一个大胖子,有多少吃多少
2.在方法当中,如果出了可变参数以外,还有其他的形参,那么可变参数要写在最后

getSum( ...args: 1,2,3,4,5,6,7,8,9,10);

public static int getsum( int a,int. . .args)

collections

java.util.Collections:是集合工具类
作用:Collections不是集合,而是集合的工具类。
在这里插入图片描述

带有概率的随机点名

//1.创建集合
ArrayList<Integer> list = new ArrayList<>();

//2.添加数据
collections.addALl(list,...elements: 1,1,1,1,1,1,1);
collections.addALl(list,...elements: 0,0,0);
//3.打乱集合中的数据
collections.shuffle(list);

//4.从list集合中随机抽取日或者1Random r = new Random();
int index = r.nextInt(list.size( ));int number = list.get(index);
System.out.println(number);

//5.创建两个集合分别存储男生和女生的名字
ArrayList<string> boyList = new ArrayList<>();
ArrayList<string> girlList = new ArrayList<>();
collections.addAll(boyList ...elements: "范闲" "范建","范统" ,"杜子腾""宋合泛","侯笼藤","朱益群","朱穆朗玛峰");
collections.addAll(girlList...elements: "杜琦燕" ,"袁明媛","李猜","田蜜蜜");

//6.判断此时是从boyList里面抽取还是从gir1List里面抽取
if(number == 1){
// boyList
int boyIndex = r.nextInt( boyList.size());string name = boyList.get( boyIndex);
system.out.println(name);
}else{
//girlList
int gir1Index = r.nextInt(girlList.size());
string name = girlList.get(girlIndex) ;
system.out.println(name) ;
}

-不重复的随机点名

//1.定义集合
ArrayList<String> list1 = new ArrayList<>();

//2.添加数据
collections.addALl(list1,...elements: "范闲""范建""范统""杜子腾",
"杜琦燕""宋合泛""侯笼藤""朱益群""朱穆朗玛峰","
//创建一个临时的集合,用来存已经被点到学生的名字
ArrayList<string> list2 = new ArrayList<>();
//外循环:表示轮数
for (int i = 1; i <= 10; i++)i
System.out.print1n("==s=a====第" + i +"轮点名开始了=======日日日日===========");
// 3.获取集合的长度
int count = list1.size();
//4.随机点名
Random r = new Random( );
//内循环:每一轮中随机循环抽取的过程
for (int j = 0; j < count; j++) {
int index = r.nextInt(list1.size());
string name = list1.remove(index);
list2.add(name) ;
system.out.print1n(name) ;
}
//此时表示一轮点名结束
//list1 空了  list2 10个学生的名字
list1.addA11(list2);
list2.clear();
}
}

34 不可变集合

可变集合是指在创建后不能再被修改的集合。在Java中,不可变集合的实现方式是通过使用一些特殊的类,它们拥有和普通集合类相似的接口,但是不允许修改操作(比如添加、删除、修改等)。如果需要修改集合,只能通过创建一个新的集合来实现。

Java中常见的不可变集合类包括:

不可变List:使用java.util.Collections.unmodifiableList()方法创建。
不可变Set:使用java.util.Collections.unmodifiableSet()方法创建。
不可变Map:使用java.util.Collections.unmodifiableMap()方法创建。

不可变集合的特点:

线程安全:由于不可变集合不能被修改,所以不会存在并发修改的情况,因此线程安全。
安全传递:由于不可变集合不能被修改,所以可以安全的作为函数参数或者返回值进行传递。
性能优化:不可变集合在创建后,其内部结构不再发生改变,因此可以进行一些优化来提高性能,如可以缓存集合的hashcode和size。

使用不可变集合的注意事项:

不可变集合不能进行修改操作,否则会throw UnsupportedOperationException异常。
对原来的集合进行修改操作,会影响不可变集合。
不可变集合只是不能被直接修改,但如果集合元素是对象,那么对象的属性仍然可以修改。

在这里插入图片描述

public class ImmutableDemo1 {
public static void main(String[]args) {


}

ctrl + Alt + V自动生成左边

细节:
当我们要获取一个不可变的Set集合时.里面的参数一定要保证唯一性

创建Map的不可变集合
细节1:
键是不能重复的
细节2:
Map里面的of方法,参数是有上限的,最多只能传递20个参数,10个键值对

/*
创建Map的不可变集合,键值对的数量超过10个
*/
//1.创建一个普通的Map集合
HashMap<string,string> hm = new HashMap<>();
hm.put("张三""南京");
hm.put("李四""北京");
hm.put("王五""上海");
hm.put("赵六""北京");
hm.put("孙七""深圳");
hm.put("周八""杭州");
hm.put("吴九""宁波");
hm.put("郑十""苏州");
hm.put("刘一""无锡");
hm.put("陈二""嘉兴");
hm.put( "aaa", "111");
//2.利用上面的数据

-初爽Stream流

ArrayList<String> list1 = new ArrayList<>();
list1.add("张无忌");
list1.add("周芷若");
list1.add("赵敏");
list1.add("张强");
list1.add("张三丰");

list1.stream().filter(name->name.startswith("张")).filter(name -> name.length() == 3 ).forEach(name->) System.out.println(name);

Stream流的思想和获取

在这里插入图片描述

Stream流的使用步骤:

  1. 先得到一条Stream流(流水线),并把数据放上去
  2. 使用中间方法对流水线上的数据进行操作
  3. 使用终结方法对流水线上的数据进行操作
    在这里插入图片描述

使用Stream流主要分为以下几个步骤:

创建一个Stream流对象:可以从集合中创建,也可以通过Stream.of()方法创建。

进行中间操作:使用filter()等中间方法对数据进行过滤、映射和聚合等操作,返回的仍然是Stream流对象。

进行终止操作:使用forEach()等终止方法获取最终结果。

下面通过一个例子来演示Stream流的使用。

假设有一个List集合,我们需要获取集合中所有的偶数并将它们打印出来。传统的方法需要使用for循环进行遍历,而使用Stream流可以更加简洁和优雅:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// 创建Stream流对象
Stream<Integer> stream = list.stream();

// 进行中间操作
stream.filter(i -> i % 2 == 0)
      .forEach(System.out::println);  // 打印结果:2 4 6 8 10

//1.单列集合获取Stream流
ArrayList<string> list = new ArrayList<>();
collections.addALl(list,...elements: "a" ,"b","c","d" ,"e");


/*//获取到一条流水线,并把集合中的数据放到流水线上
Stream<String> stream1 = list.stream( );
//使用终结方法打印一下流水线上的所有数据
stream1.forEach(new Consumer<String>() i
@Override
public void accept(String s) i
//s:依次表示流水线上的每一个数据
System.out.print1n(s);
}
});*/

list.stream( ).forEach(s -> system.out. println(s));

//1.创建双列集合
HashMap<String,Integer> hm = new HashMap<>();
//2.添加数据
hm.put( "aaa",111);
hm.put( "bbb",222);
hm.put( "ccc",333);
hm.put( "ddd",444);
//3.获取stream流
hm.keySet( ).stream().forEach(s -> system.out.println(s));
//keySet( )必要
//4.第二种获取stream流
hm.entrySet().stream( ).forEach(s-> System.out.println(s));

public static void main( String[]args) {
//数组 public static <T> Stream<T> stream(T[] array)    Arrays工具类中的静态方法
//1.创建数组
int[] arr1 = {1,2,3,4,5,6,7,8,9,10};
string[] arr2 = {"a","b","c"};
//2.获取stream流
Arrays.stream(arr1 ).forEach(s-> system.out.println(s));
system.out.println("========================");
Arrays.stream(arr2).forEach(s-> System.out.println(s));

//一堆零散数据 public static<T> Stream<T> of(T. . . values)    stream接口中的静态方法
Stream.of(1,2,3,4,5).forEach(s-> system.out.println(s));
Stream.of("a", "b","c", "d" , "e").forEach(s-> System.out.println(s));

Stream流的中间方法

在这里插入图片描述
注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据

//过滤
list.stream()
.filter(s -> s.startswith("张"))
.filter(s -> s.length() == 3)
.forEach(s -> system.out.println(s));

// distinct 元素去重,依赖(hashCode和equals方法)
list1.stream( ).distinct( ).forEach(s -> system.out.println(s));
//合并
Stream.concat(list1.stream(),list2.stream()).forEach(s -> System.out.println(s));

//当map方法执行完毕之后,流上的数据就变成了整数
//所以在下面forEach当中,s依次表示流里面的每一个数据,这个数据现在就是整数了
list.stream()
.map( s-> Integer.parseInt( s.split( regex:"-")[1]))
.forEach(s-> system.out.println(s));

Stream流的终结方法

在这里插入图片描述
void forEach(Consumer action)
遍历
long count()
统计
toArray()
收集流中的数据,放到数组中

//toArray方法的参数的作用:负责创建一个指定类型的数组
//toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组当中
//toArray方法的返回值:是一个装着流里面所有数据的数组

-收集方法collect超详解

**collect(collector collector)
收集流中的数据,放到集合中(List set Map)
**
collect(collector collector)
收集流中的数据,放到集合中(List set Map)

注意点:
如果我们要收集到Map集合当中,键不能重复,否则会报错


toMap :参数一表示键的生成规则
参数二表示值的生成规则
参数一:
Function泛型一:表示流中每一个数据的类型
泛型二:表示Map集合中键的数据类型
方法apply形参:依次表示流里面的每一个数据
方法体:生成键的代码
返回值:已经生成的键
参数二:
Function泛型一:表示流中每一个数据的类型
泛型二:表示Map集合中值的数据类型
方法apply形参:依次表示流里面的每一个数据
方法体:生成值的代码
返回值:已经生成的值

练习1

/*
定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10过滤奇数,只留下偶数。
并将结果保存起来
心
*/
//1.定义一个集合
ArrayList<Integer> list = new ArrayList<>();
//2.添加一些整数
collections.addAll(1list,...elements: 12345678910);
//3.过滤奇数,只留下偶数
//进行判断,如果是偶数,返回true保留list.stream()
.filter(n -> n % 2 == )
.forEach(n -> system.out.println(n) );
//4.打印集合
system.out.println( newList);

lambda表达式 {} return ; 可以省略

43-方法引用概述

在这里插入图片描述

  1. 被引用的方法必须已经存在
  2. 被引用方法的形参和返回值
    需要跟抽象方法保持一致
  3. 被引用方法的功能要满足当前需求

-引用静态方法

方法引用的分类

  1. 引用静态方法
  2. 引用成员方法
  3. 引用构造方法

引用其他类的成员方法
引用本类的成员方法
引用父类的成员方法

引用静态方法
格式:类名::静态方法
范例:Integer : : parseInt

引用其他类的成员方法

方法引用(引用成员方法)格式
其他类:其他类对象::方法名
本类: this ::方法名
父类: super: :方法名
引用构造方法
格式:类名::new
范例:student: : new

类名引用成员方法

格式:类名:成员方法
范例:string : : substring

方法引用的规则:

  1. 需要有函数式接口
  2. 被引用的方法必须已经存在
  3. 被引用方法的形参,需要跟抽象方法的第二个形参到最后一个形参保持一致,返回值需要保持一致。
  4. 被引用方法的功能需要满足当前的需求

抽象方法形参的详解:

第一个参数:
表示被引用方法的调用者,决定了可以引用哪些类中的方法
在Stream流当中,第一个参数一般都表示流里面的每一个数据。
假设流里面的数据是字符串,那么使用这种方式进行方法引用,只能引用string这个类中的方法
第二个参数到最后一个参数:
跟被引用方法的形参保持一致,如果没有第二个参数,说明被引用的方法需要是无参的成员方法

引用数组的构造方法

引用数组的构造方法
格式:数据类型[: :new范例:int[ ] ::new
在这里插入图片描述

异常体系介绍

在这里插入图片描述
Exception:叫做异常,代表程序可能出现的问题。
我们通常会用Exception以及他的子类来封装程序出现的问题

运行时异常:RuntimeException及其子类,编译阶段不会出现异常提醒。
运行时出现的异常(如:数组索引越界异常)

编译时异常:编译阶段就会出现异常提醒的。

编译时异常(在编译阶段,必须要手动处理,否则代码报错)
运行时异常(在编译阶段是不需要处理的,是代码运行时出现的异常)

异吊的作用
作用一:异常是用来查询bug的关键参考信息
作用二:异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况

自己处理(捕获异常)格式:
try {
可能出现异常的代码;
}catch(异常类名变量名){
异常的处理代码;
}
好处:可以让程序继续往下执行,不会停止
在这里插入图片描述
灵魂一问:如果try中没有遇到问题,怎么执行?
会把try里面所有的代码全部执行完毕,不会执行catch里面的代码注意:
只有当出现了异常才会执行catch里面的代码

灵魂二问:如果try中可能会遇到多个问题,怎么执行?
会写多个catch与之对应
细节:
如果我们要捕获多个异常,这些异常中如果存在父子关系的话,那么父类一定要写在下面

灵魂三问:如果try中遇到的问题没有被捕获,怎么执行?
相当于try. . .catch的代码白写了,最终还是会交给虚拟机进行处理。

灵魂四问:如果try中遇到了问题,那么try下面的其他代码还会执行吗?
下面的代码就不会执行了,直接跳转到对应的catch当中,执行catch里面的语句体但是如果没有对应catch与之匹配,那么还是会交给虚拟机进行处理

异常中的常见方法

在这里插入图片描述
ctrl + alt +T 包裹代码

//正常的输出语句
//system.out.println(123);
错误的输出语句(而是用来打印错误信息)
system.err.println(123);

抛出异常

在这里插入图片描述

int[] arr = i;
int max = getMax( arr);
system.out.println(max);

}

public static int getMax ( int[ ]arr){
if( arr == null){
//手动创建一个异常对象,并把这个异常交给方法的调用者处理
//此时方法就会结束,下面的代码不会再执行了
throw new NullPointerException( );
}
system.out.println("看看我执行了吗? ");
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i] > max){
max = arr[i];
}
}
return max;
}

-自定义异常

在这里插入图片描述
技巧:
NameFormat:当前异常的名字,表示姓名格式化问题
Exception:表示当前类是一个异常类

运行时: RuntimeException核心就表示由于参数错误而导致的问题
编译时:Exception核心提醒程序员检查本地信息

63File

●File对象就表示一个路径,可以是文件的路径、也可以是文件夹的路径
●这个路径可以是存在的,也允许是不存在的

在这里插入图片描述

//2.父级路径:C: \Users\alienware\Desktop
//子级路径: a.txt
string parent = "c: \\Users\\alienware \\Desktop";
String child = "a.txt" ;
File f2 = new File(parent,child);
system.out.println(f2);//C : \Users \alienware\Desktop\a.txt

File的成员方法(判断、获取)

在这里插入图片描述

File的成员方法(创建、删除)

在这里插入图片描述
1.createNewFile创建一个新的空的文件
细节1:
如果当前路径表示的文件是不存在的,则创建成功,方法返回true
如果当前路径表示的文件是存在的,则创建失败,方法返回false

细节2:
如果父级路径是不存在的,那么方法会有异常IOException

细节3:
createNewFile方法创建的一定是文件,如果路径中不包含后缀名,则创建个没有后缀的文件

File f1 = new File("D: \\aaa \\ddd" );
boolean b = f1.createNewFile();
system.out.println(b); //true

2.mkdir make Directory,文件夹(目录)
细节1:
windows当中路径是唯一的,如果当前路径已经存在,则创建失败,返回false
细节2:
mkdir方法只能创建单级文件夹,无法创建多级文件夹。

File f2 = new File("D: \ laaa \ laaa \ lbbb\lccc");
boolean b = f2.mkdir();
system.out.println(b);

public boolean delete()
删除文件、空文件夹
细节1:
如果删除的是文件,则直接删除,不走回收站。如果删除的是空文件夹,则直接删除,不走回收站如果删除的是有内容的文件夹,则删除失败

File的成员方法(获取并遍历)

在这里插入图片描述
当调用者File表示的路径不存在时,返回null
当调用者File表示的路径是文件时,返回null
当调用者File表示的路径是一个空文件夹时,返回一个长度为0的数组
当调用者File表示的路径是一个有内容的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回
当调用者File表示的路径是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
当调用者File表示的路径是需要权限才能访问的文件夹时,返回null

//1.创建File对象
File f = new File( pathname: "D: \\aaa" );
//2.listFiles方法
//作用:获取aaa文件夹里面的所有内容,把所有的内容放到数组中返回
File[ ] files = f.listFiles();
for (File file : files) {
//file依次表示aaa文件夹里面的每一个文件夹心
}

74-IO流的概述

IO流
用于读写文件中的数据(可以读写文件,或网络中的数据…)
在这里插入图片描述
在这里插入图片描述

-IO流的体系和字节输出流基本用法

在这里插入图片描述

实现步骤

创建对象

写出数据

释放资源

//1.创建对象
//写出输出流OutputStream
//本地文件File
FileOutputstream fos = new Fileoutputstream( name: "myio\la.txt" );
//2.写出数据
fos.write( b: 97);
//3.释放资源
fos.close();

字节输出流写出数据的细节

字节输出流的细节:
1.创建字节输出流对象
细节1:参数是字符串表示的路径或者是File对象都是可以的
细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。细节3:如果文件已经存在,则会清空文件
2.写数据
细节: write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
3.释放资源
每次使用完流之后都要释放资源
/l1.创建对象
FileoutputStream fos = new FileoutputStream( name: "myiolla.txt" );//2.写出数据
fos.write( b: 57);
fos.write( b: 55);
//3.释放资源
fos.close();
while(true){}

字节输出流写出数据的三种方式

在这里插入图片描述

换行和续写

换行写:
再次写出一个换行符就可以了
windows:\r\n
Linux :\n
Mac:\r

string wrap = "\r\n";
byte[ ] bytes2 = wrap.getBytes();
fos.write(bytes2);

续写:
如果想要续写,打开续写开关即可开关位置:创建对象的第二个参数
默认false:表示关闭续写,此时创建对象会清空文件手动传递true:表示打开续写,此时创建对象不会清空文件

-字节输入流的基本用法

*实现步骤:
*
创建对象
*
读取数据
*
释放资源

//1.创建对象
FileInputStream fis = new FileInputStream( name: "myio\la.txt");
//2.读取数据
int b1 = fis.read( );
system.out.print1n(b1);//System.out.println( ( char)b1);
//强转
//3.释放资源
fis.close();

字节输入流读取数据的细节

创建字节输入流对象
细节1∶如果文件不存在,就直接报错。
②读取数据
细节1:一次读一个字节,读出来的是数据在ASClI上对应的数字
细节2:读到文件末尾了,read方法返回-1。
③释放资源
细节1:每次使用完流必须要释放资源。

字节输入流循环读取

要定义变量

//1.创建对象
FileInputStream fis = new FileInputStream( name: "myiolla.txt");
//2.循环读取
int b;//定义变量
while ((b = fis.read()) != -1) {
system.out.println( ( char) b);
}
//3.释放资源fis.close();

read :表示读取数据,而且是读取一个数据就移动一次指针

文件拷贝的基本代码

//1.创建对象
FileInputstream fis = new FileInputstream( name: "D:\litheimal\movie.mp4");
FileOutputStream fos = new Fileoutputstream( name: "myio\\copy.mp4");
//2.拷贝
//核心思想:边读边写
int b;
while((b = fis.read()) != -1){
fos.write(b);
}
//3.释放资源
//规则:先开的最后关闭
fos.close();
fis.close();

文件拷贝的弊端和解决方案

/*
public int read( byte[ ] buffer)
一次读一个字节数组数据
*/
//1.创建对象
FileInputstream fis = new FileInputstream( name: "myio\\a.txt");
//2.读取数据
byte[] bytes = new byte[2];
//一次读取多个字节数据,具体读多少,跟数组的长度有关
//返回值:本次读取到了多少个字节数据
int len = fis.read(bytes);
system.out.println( len); 
//2
String str = new String(bytes);
system.out.println( str);
//3.释放资源
fis.close();

数组数据残留
解决方案
在这里插入图片描述


文件拷贝改写

long start = system.currentTimeMillis();
//1.创建对象
FileInputStream fis = new FileInputStream( name:"D:\litheimal\movie.mp4");
FileOutputstream fos = new FileOutputstream( name: "myio\lcopy.mp4" );
//2.拷贝
int len;
byte[ ] bytes = new byte[1024*1024*5];
while((len = fis.read(bytes)) != -1){
fos.write(bytes, off: 0,len);
}
//3.释放资源
fos.close( );
fis.close();
long end = system.currentTimeMillis( );
system.out.println(end - start);

-IO流中不同JDK版本捕获异常的方式

//1.创建对象
FileInputStream fis = null;
Fileoutputstream fos = null;
try {
fis = new FileInputstream( name: "D:\litheima\\movie.mp4" );
fos = new FileoOutputstream( name: "myiollcopy.mp4");
//2.拷贝
int len;
byte[] bytes = new byte[ 1024*1024* 5];
while((len = fis.read(bytes)) != -1){
fos.write(bytes, off: e,len);
}
catch ( IOException e) {
// e.printStackTrace( );
}finally {
// 3.释放资源

if(fos != null){
try {
fos.close();
}catch ( IOException e) {
e.printstackTrace();
}
}
if(fis != nul1){
try {
fis.close();
}catch ( IOException e) {
e.printStackTrace( );
}


在这里插入图片描述

  1. 在计算机中,任意数据都是以二进制的形式来存储的
  2. 计算机中最小的存储单元是一个字节
  3. ASCII字符集中,一个英文占一个字节
  4. 简体中文版windows,默认使用GBK字符集
  5. GBK字符集完全兼容ASCII字符集
    一个英文占一个字节,二进制第一位是0
    一个中文占两个字节,二进制高位字节的第一位是1
    在这里插入图片描述
  6. Unicode字符集的UTF-8编码格式
    一个英文占一个字节,二进制第一位是0,转成十进制是正数

如何不产生乱码?
1,不要用字节流读取文本文件
2,编码解码时使用同一个码表,同一个编码方式

Java中编码和解码的代码实现

Java中编码的方法
public byte[] getBytes()使用默认方式进行编码
public byte[] getBytes(String charsetName)使用指定方式进行编码
Java中解码的方法
String( byte[] bytes)使用默认方式进行解码
String( byte[] bytes, string charsetName)使用指定方式进行解码

//1.编码
string str = "ai你哟";
byte[ ] bytes1 = str.getBytes();
system.out.println(Arrays.tostring( bytes1));
byte[] bytes2 = str.getBytes( charsetName: "GBK");system.out.println(Arrays.toString(bytes2));
//2.解码
string str2 = new String(bytes1);
system.out.println(str2);
String str3 = new string(bytes1,charsetName: "GBK");
system.out.println(str3);

字符输入流-空参read方法详解

在这里插入图片描述
在这里插入图片描述
第一步:创建对象
public FileReader(File file)创建字符输入流关联本地文件
public FileReader(String pathname)创建字符输入流关联本地文件
第二步:读取数据
public int read()读取数据,读到末尾返回-1
public int read(char[] buffer)读取多个数据,读到末尾返回-1
第三步:释放资源
public void close()释放资源/关流
//我想看到中文汉字,就是把这些十进制数据,再进行强转就可以了

int ch;
while((ch = fr.read()) != -1)i
system.out.print( ( char)ch) ;

read ()细节:
1.read():默认也是一个字节一个字节的读取的,如果遇到中文就会一次读取多个
2.在读取之后,方法的底层还会进行解码并转成十进制。
最终把这个十进制作为返回值
这个十进制的数据也表示在字符集上的数字
英文:文件里面二进制数据0110 0801
read方法进行读取,解码并转成十进制97
中文:文件里面的二进制数据11100110 10110801 10801001
read方法进行读取,解码并转成十进制27721


字符流和字节流是java中输入输出流的两种方法。简单来说:

字节流操作的是文件的二进制数据,主要用于读写二进制文件(如图片、音频等);
字符流则操作的是文本数据(如txt、html等),对二进制文件进行处理时一般需要用字节流。

具体可以看以下的详解:

字节流

Java中的字节流按照操作方向分为输入流和输出流。

输入流:InputStream,常用方法有 read() 和 read(byte[] b)。read() 一次读取一个字节,返回值为读取到的字节,当读取到尾部时返回 -1。read(byte[] b) 一次读取一组字节,返回值为读取到的总字节数,当读取到尾部时返回 -1。
输出流:OutputStream,常用方法有 write(int b) 和 write(byte[] b)。write(int b) 将给定的字节写入输出流,write(byte[] b) 将 byte 数组 b 中的所有字节写入输出流。

字符流

Java中的字符流也按照操作方向分为输入流和输出流。

输入流:Reader,常用方法有 read() 和 read(byte[] b)。read() 一次读取一个字符(Unicode),返回值为读取到的字符,当读取到尾部时返回 -1。read(char[] b) 一次读取一组字符,返回值为读取到的总字符数,当读取到尾部时返回 -1。
输出流:Writer,常用方法有 write(int c) 和 write(char[] c)。write(int c) 将给定的字符写入输出流,write(char[] c) 将字符数组 c 中的所有字符写入输出流。

字符输入流-有参read方法详解

read(chars):读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中/空参的read +强转类型转换

字符流输出流写出数据

在这里插入图片描述
void write(string str)
写出一个字符串

加密

^异或
两边相同:false
两边不同: true
0: false
1: true

字节缓冲流拷贝文件

在这里插入图片描述

//1.创建缓冲流的对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream( name: "myiolla.txt"));
BufferedoutputStream bos = new BufferedOutputStream(new FileOutputStream( name: "myiollcopy.txt"));//2.循环读取并写到目的地
int b;
while ((b = bis.read()) != -1) i
bos.write(b);
}
//3.释放资源
bos.close();
 bis.close();


//2.拷贝(一次读写多个字节)
byte[ ] bytes = new byte[ 1024];int len;
while((len = bis.read(bytes)) != -1){
bos.write(bytes, off: 0,len);
}

在这里插入图片描述

字符缓冲流

在这里插入图片描述
readLine方法在读取的时候,一次读一整行

字符缓冲输入流

//1.创建字符缓冲输入流的对象
BufferedReader br = new BufferedReader(new FileReader( fileName: "myio\la.txt"));
//2.读取数据
//细节;
// readLine方法在读取的时候,一次读一整行,遇到回车换行结束
//但是他不会把回车换行读到内存当中
/*string line1 = br.readLine();
system.out.println( line1);
String line2 = br.readLine( );
system.out.println(line2);*/
string line;
while ((( line = br.readLine( )) != null)){
system.out.println( line);
}

特有方法:
public void newLine( )
跨平台的换行
//1.创建字符缓冲输出流的对象
Bufferedwriter bw = new Bufferedwriter(new Filewriter( fileName: "b.txt"));
//2.写出数据
bw.write( str:"你嘴角上扬的样子,百度搜索不到");
bw.newLine( );
bw.write( str:"以后如果我结婚了,你一定要来哦,没有新娘我会很尴尬");
bw.newLine( );
//3.释放资源
bw.close( );

-转换流基本用法

在这里插入图片描述
在这里插入图片描述

FileReader fr = new FileReader( fileName: "myiolIgbkfile.txt" , Charset.forName("GBK"));
//2.读取数据
int ch;
while ((ch = fr.read()) != -1){
system.out.print( (char)ch);
}
//3.释放资源fr.close( );

利用转换流按照指定字符编码写出

Filewriter fw = new Filewriter( fileName: "myio\\c.txt" , Charset.forName("GBK"));fw.write( str:“你好你好");
fw.close( );

/*
将本地文件中的GBK文件,转成UTF-8*/
//1.JDK11以前的方案
InputStreamReader isr = new InputStreamReader(new FileInputStream( name:"myiol|b.txt" ), charsetName: "GBK");
outputStreamwniter osw = new OutputStreamw/riter(new FileOutputStream( name:"myiol|d.txt" ), charsetName: "UTF-8");
int b;
while((b = isr.read()) != -1){
osw.write(b);
}
osw.close( );
isr.close();
}
}
//2.替代方案
FileReader fr = new FileReader( fileName: "myiollb.txt"Charset.forName("GBK"));Filewriter fw = new Filewriter( fileName: "myiolle.txt" , Charset.forName( "UTF-8"));int b;
while ((b = fr.read()) != -1){
fw.write(b);
}
fw.close( );
fr.close();

利用字节流读取文件中的数据,每次读一整行,而且不出现乱码
//1.字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定
//2.字节流里面是没有读一整行的方法的,只有字符缓冲流才能搞定

序列化流

可以把Java中的对象写到本地文件中
构造方法:
public objectoutputStream(OutputStream out)
把基本流变成高级流
成员方法:
public final void writeobject(object obj)
把对象序列化(写出)到文件中去

//1.创建对象
Student stu = new Student( name: "zhangsan", age: 23);
//2.创建序列化流的对象/对象操作输出流
objectoutputStream oos = new objectOutputStream(new FileoutputStream
(name:"myio\la.txt"));
// 3.写出数据
oos.writeobject(stu);
//4.释放资源
oos.close();

序列化流的小细节
使用对象输出流将对象保存到文件时会出现NotSerializableException异常
解决方案:需要让Javabean类实现Serializable接口

Serializable接口里面是没有抽象方法,标记型接口
一旦实现了这个接口,那么就表示当前的Student类可以被序列化
理解:
一个物品的合格证

反序列化流/对象操作输入流

可以把序列化到本地文件中的对象,读取到程序中来
在这里插入图片描述

//1.创建反序列化流的对象
objectInputStream ois = new ObjectInputStream(new FileInputStream( name: "myiolla.txt"));
//2.读取数据
student o = ( Student) ois.readObject();
//3.打印对象
System.out.println(o);
//4.释放资源
ois.close();

在这里插入图片描述

字节打印流

在这里插入图片描述

字符打印流

在这里插入图片描述

//获取打印流的对象,此打印流在虚拟机启动的时候,由虚拟机创建,默认指向控制台
//特殊的打印流,系统中的标准输出流,是不能关闭,在系统中是唯一的。
PrintStream ps = system.out;
//调用打印流中的方法printlnl/写出数据,自动换行,自动刷新
ps.println( "123");
// ps.close();

ps.println("你好你好");
System.out.println("456");

解压

//创建一个解压缩流用来读取压缩包中的数据
ZipInputstream zip = new ZipInputstream(new FileInputstream( src) );
//要先获取到压缩包里面的每一个zipentry对象

//表示当前在压缩包中获取到的文件或者文件夹zipEntry entry;
while((entry = zip.getNextEntry()) != null){
system.out.println(entry);
if(entry.isDirectory()){
//文件夹:需要在目的地dest处创建一个同样的文件夹
File file = new File(dest,entry.tostring());
file.mkdirs();
else{
//文件:需要读取到压缩包中的文件,并把他存放到目的地dest文件夹中(按照层级目录进行存放)Fileoutputstream fos = new FileOutputStream(new File(dest,entry.toString()));int b;
while((b = zip.read()) != -1){
//写到目的地
fos.write(b);
}
fos.close( );
//表示在压缩包中的一个文件处理完毕了。zip.closeEntry();
}
}
zip.close();

//1.创建File对象表示要压缩的文件
File src = new File( pathname: "D: \l la.txt" );
//2.创建File对象表示压缩包的位置
File dest = new File( pathname: "D: \l");
// 3.调用方法用来压缩
toZip(src,dest);
}
/*
作用:压缩
*参数一:表示要压缩的文件*参数二:表示压缩包的位置**/
public static void toZip(File src,File dest) throws IOException {
//1.创建压缩流关联压缩包
ZipoutputStream zos = new ZipoutputStream( new FileOutputStream(new File(dest, child: "a.zip")));
//2.创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
zipEntry entry = new ZipEntry( name: "a.txt" );
//3.把ZipEntry对象放到压缩包当中
zos.putNextEntry(entry);
//4.把src文件中的数据写到压缩包当中
FileInputstream fis = new FileInputStream( src);
int b; 
while((b = fis.read()) != -1){
zos.write(b);
}

Hutool工具包

在这里插入图片描述

-什么是多线程?

  1. 并发:在同一时刻,有多个指令在单个CPU上交替执行

  2. 并行:在同一时刻,有多个指令在多个CPU上同时执行

在这里插入图片描述

public class Main {
    public static void main(String[] args) {
         MyThread t1 = new MyThread();
         MyThread t2 = new MyThread();

         t1.setName("xc1");
         t2.setName("xc2");
         t1.start();
         t2.start();

    }
}

多线程的第二种启动方式:
1.自己定义一个类实现Runnable接口
2.重写里面的run方法
3.创建自己的类的对象
4.创建一个Thread类的对象,并开启线程

MyRun mr = new MyRun();
//创建线程对象
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
//开启线程
t1.start( );
t2.start();

/**
多线程的第三种实现方式:
*
特点:可以获取到多线程运行的结果
*
*
1.创建一个类MyCallable实现callable接口
*
2.重写cal1(是有返回值的,表示多线程运行的结果)
*
*
3.创建Mycallable的对象(表示多线程要执行的任务)
*
4.创建FutureTask的对象(作用管理多线程运行的结果)
*
5.创建Thread类的对象,并启动(表示线程>
**/
//创建MyCallable的对象(表示多线程要执行的任务)
Mycallable mc = new Mycallable( );
//创建FutureTask的对象(作用管理多线程运行的结果)
FutureTask<Integer> ft = new FutureTask<>(mc );//创建线程的对象
Thread t1 = new Thread(ft);//启动线程
t1.start( );
//获取多线程运行的结果
Integer result = ft.get();System.out.println(result);

在这里插入图片描述

多线程中的常用成员方法

在这里插入图片描述

string getName()返回此线程的名称
void setName(string name)设置线程的名字(构造方法也可以设置名字
细节:
1、如果我们没有给线程设置名字,线程也是有默认的名字的
格式: Thread-X(X序号,从0开始的)
2、如果我们要给线程设置名字,可以用set方法进行设置,也可以构造方法设置

static Thread currentThread( )获取当前线程的对象

细节:
当JVM虚拟机启动之后,会自动的启动多条线程
其中有一条线程就叫做main线程
他的作用就是去调用main方法,并执行里面的代码
在以前,我们写的所有的代码,其实都是运行在main线程当中

static void sleep(long time)
让线程休眠指定的时间,单位为毫秒

细节:
1、哪条线程执行到这个方法,那么哪条线程就会在这里停留对应的时间
2、方法的参数:就表示睡眠的时间,单位毫秒1= 1000毫秒
3、当时间到了之后,线程会自动的醒来,继续执行下面的其他代码

在这里插入图片描述

public void run( ) {
//1.循环心while(true){
//2.同步代码块(同步方法)
synchronized (MyRunnable.class){
//3.判断共享数据是否到了末尾,如果到了末尾
if(ticket == 100){
break;
}else{
//4.判断共享数据是否到了末尾,如果没有到末尾
ticket++;
System.out.print1n(Thread.currentThread( ).getName( ) +
"在卖第"+ ticket +"张票!!!");
}
}
}
}

lock锁

在这里插入图片描述

生产者和消费者

void wait()]
当前线程等待,直到被其他线程唤醒
void notify()
随机唤醒单个线程
void tnotifyAll()
唤醒所有线程
在这里插入图片描述

在这里插入图片描述

线程池

线程池主要核心原理
创建一个池子,池子中是空的
提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给池子下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可
在这里插入图片描述
在这里插入图片描述

 

在这里插入图片描述

在这里插入图片描述

线程池多大合适呢?

在这里插入图片描述

多线程的额外扩展内容

面试:
线程的状态
线程池
volatile
JMM
悲观锁、乐观锁、CAS
原子性
并发工具类

-初始网络编程

常见的软件架构

BS架构的优缺点
01不需要开发客户端,只需要页面+服务端
02用户不需要下载,打开浏览器就能使用
03如果应用过大,用户体验受到影响

CS架构的优缺点
画面可以做的非常精美,用户
01体验好
02需要开发客户端,也需要开发服务端


网络编程三要素
lP 设备在网络中的地址,是唯一的标识。

端口号 应用程序在设备中唯一的标识。

协议 数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp

特殊IP地址
127.0.0.1,也可以是localhost:是回送地址也称本地回环地址,也称本机IP,永远只会寻找当前所在本机

常用的CMD命令
ipconfig:查看本机IP地址
ping:检查网络是否连通

static InetAddress getByName(String host)确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
string getHostName( )获取此IP地址的主机名
string getHostAddress()返回文本显示中的IP地址字符串

端口号

应用程序在设备中唯一的标识。
端口号:由两个字节表示的整数,取值范围:0~65535
其中0~1023之间的端口号用于一些知名的网络服务或者应用。我们自己使用1024以上的端口号就可以了。
注意:一个端口号只能被一个应用程序使用。

协议

计算机网络中,连接和通信的规则被称为网络通信协议

  1. OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推广
  2. TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
    在这里插入图片描述
    在这里插入图片描述
    UDP协议
    用户数据报协议(User Datagram Protocol)UDP是面向无连接通信协议。
    速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
    TCP协议
    传输控制协议TCP(Transmission Control Protocol)TCP协议是面向连接的通信协议。
    速度慢,没有大小限制,数据安全。
//1.创建DatagramSocket对象(快递公司)
//细节:
//绑定端口,以后我们就是通过这个端口往外发送
//空参:所有可用的端口中随机一个进行使用
//有参:指定端口号进行绑定
DatagramSocket ds = new DatagramSocket( );
//2.打包数据
String str =“你好威啊!!!";
byte[] bytes = str.getBytes( );
InetAddress address = InetAddress.getByName( "127.0.0.1");
int port = 10086;

DatagramPacket dp = new DatagramPacket(bytes,bytes.length,address,port);
//3.发送数据
ds.send(dp ) ;
//4.释放资源
ds.close();

//1.创建DatagramSocket对象(快递公司)
//细节:
//在接收的时候,一定要绑定端口
//而且绑定的端口一定要跟发送的端口保持一致
DatagramSocket ds = new DatagramSocket( port: 10086);
//2.接收数据包
byte[] bytes = new byte[ 1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
//3.解析数据包
byte[] data = dp.getData( );
int len = dp.getLength();
InetAddress address = dp.getAddress( );
int port = dp.getPort( );
system.out.print1n("接收到数据" +new string(data, offset: 8,len));
System.out.println("该数据是从"+ address +"这台电脑中的"+ port +"这个端口发出的");
//4.释放资源
ds.close();

ctrl+alt+t循环包裹

单播,组播,广播

在这里插入图片描述

TCP通信程序

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象通信之前要保证连接已经建立
通过Socket产生IO流来进行网络通信

  1. 创建客户端的Socket对象(Socket)与指定服务端连接
    socket(string host,int port)
  2. 获取输出流,写数据
    outputstream getoutputstream()
  3. 释放资源
    void close()


在这里插入图片描述

反射 -获取class对象的三种方式

获取class对象的三种方式

  1. class.forName( “全类名”);
  2. 类名.class
  3. 对象.getclass();
//1.第一种方式
//全类名:包名+类名
//最为常用的

class clazz1 = class.forName( "com.itheima.myreflect1.Student" );
//2.第二种方式
Class clazz2 = Student.class;
//3.第三种方式
student s = new Student( );
class clazz3 = s.getclass();
system.out.println(clazz1 == clazz2);
system.out.println(clazz2 == clazz3);

在这里插入图片描述
在这里插入图片描述
如何复制
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值