Java乱七八糟的学习
SpringBoot
Redis
入门

因为是kv存储在内存里,所以,查询速度会比mysql快很多

Java回炉重造
增强循环
在 Java 中,增强的 for 循环(即 for (String str : split))只是对数组中每个元素的副本进行操作,不会改变原始数组 split 的内容。如果你需要修改数组中的元素,你应该使用传统的 for 循环来进行操作,例如:
| 1 | for (int i = 0; i < split.length; i++) { | 
这样可以直接修改 split 数组中的每个元素。
内存分配


关于数组的内存

关于方法的内存

值传递

这个是方法的值传递,形参在方法中的改变不会影响数组的值。
引用类型传递

引用类型直接到堆中改变的值,所以是可以影响到本来数组的值的。
字符串

注意看注释,其实还蛮有用的(对于计算机网络来说
new String(b, 0, len) 是创建一个新的字符串对象的语法,其中 b 是一个字节数组,0 是起始索引,len 是有效字节的个数。
内存


所以再创建新的字符串的时候,最好用直接赋值的方式创建。
StringBuilder

使用场景

Math

那个max记得,以后可能有很大用处
BigIntager
略,反正可以放很大的值
正则表达式

值得注意的是,一个[]只能匹配一个字符(除非后面加了量词)也就是如果要验证“ab”,需要如下:
| 1 | public class ZhengZe { | 

substring包头不包尾
数组
整型数组并将其转换为列表
在Java中,你可以使用多种方式创建整型数组并将其转换为列表(List)。以下是一些常见的方法:
在Java 8中,.boxed() 是 Stream API 中的一个方法,用于将基本数据类型的流(如 IntStream、LongStream、DoubleStream)转换为对应的包装类型的流(如 Stream<Integer>、Stream<Long>、Stream<Double>)。
为什么需要 .boxed()
Java的集合框架(如 List、Set 等)只能存储对象,不能直接存储基本数据类型(如 int、long、double)。因此,当你想将基本数据类型的流转换为集合时,需要先将基本数据类型装箱(box)为对应的包装类型。
示例
假设你有一个 int[] 数组,你想将其转换为一个 List<Integer>:
| 1 | import java.util.Arrays; | 
在上面的代码中,Arrays.stream(array) 创建了一个 IntStream,然后调用 .boxed() 方法将其转换为 Stream<Integer>,最后使用 collect(Collectors.toList()) 将流收集为一个 List<Integer>。
简化写法
通常情况下,你可以将上述步骤简化为一行代码:
| 1 | List<Integer> list = Arrays.stream(array) | 
这样,.boxed() 方法会自动将 IntStream 转换为 Stream<Integer>,使得后续的收集操作可以顺利进行。
总之,.boxed() 方法用于将基本数据类型的流转换为对应的包装类型的流,以便在需要对象的地方使用。
方法一:使用Arrays.asList()方法
| 1 | import java.util.Arrays; | 
方法二:使用ArrayList构造函数
| 1 | import java.util.ArrayList; | 
方法三:使用IntStream和Collectors.toList()
| 1 | import java.util.Arrays; | 
方法四:使用Collections.addAll()方法
| 1 | import java.util.ArrayList; | 
注意事项
- 在方法一和方法三中,我们使用了Java 8引入的Stream API来处理数组和列表之间的转换。
- 在方法二和方法四中,我们使用了传统的循环和添加元素的方式来构建列表。
- 在所有方法中,我们都使用了Integer对象而不是基本数据类型int,因为Java的集合框架不支持基本数据类型,只支持对象(所有用了流中的.boxed包装类)。
选择哪种方法取决于你的具体需求和偏好。

流stream
在Java中,List 是一种常见的集合类型,用于存储一组有序的元素。Java 8引入了流(Stream)API,使得对集合的操作更加简洁和功能强大。流支持链式编程,允许你以声明式的方式对集合进行各种操作。
流的基本概念
流是一个来自数据源的元素队列,并支持聚合操作。流的操作分为两种类型:
- 中间操作:返回一个新的流,允许链式调用其他操作。
- 终端操作:触发流的处理并产生结果或副作用。
链式编程示例
假设我们有一个 List<Integer>,我们想对其进行一系列操作,例如过滤出偶数、将它们平方,然后计算总和。
| 1 | import java.util.Arrays; | 
具体操作解释
- 创建流: - 1 - numbers.stream() - 这行代码从 - List<Integer>创建了一个流。
- 过滤出偶数: - 1 - .filter(n -> n % 2 == 0) - 这行代码使用 - filter方法过滤出流中的偶数。- filter是一个中间操作,返回一个新的流。
- 将每个偶数平方: - 1 - .map(n -> n * n) - 这行代码使用 - map方法将流中的每个元素平方。- map也是一个中间操作,返回一个新的流。
- 计算总和: - 1 - .reduce(0, Integer::sum) - 这行代码使用 - reduce方法计算流中所有元素的总和。- reduce是一个终端操作,触发流的处理并产生结果。
其他常用流操作
- ** - forEach**:对流中的每个元素执行某个操作。- 1 - numbers.stream().forEach(System.out::println); 
- ** - collect**:将流中的元素收集到一个集合中。- 1 - List<Integer> evens = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList()); 
- ** - sorted**:对流中的元素进行排序。- 1 - List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList()); 
- ** - distinct**:去除流中的重复元素。- 1 - List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList()); 
总结
流API和链式编程使得对集合的操作更加简洁和功能强大。通过组合不同的中间操作和终端操作,你可以以声明式的方式对集合进行复杂的处理。这种编程方式不仅提高了代码的可读性,还减少了样板代码的编写。
lambda表达式

单列集合(除了树



集合中的引用类

关于引用类,有很多像equals这样的接口是要在引用类中重写的。

Collection
树

二叉树:普通。
二叉搜索树:比父节点小的在左,大的在右。
平衡二叉树:二叉搜索树。任意节点的左右子树高度都不超过1。
红黑树


红黑树:二叉搜索树,规则如上。(好难orz
set

hashset
哈希值

底层原理

数组+链表+红黑树
双列集合
MAP

遍历方式有三种:
| 1 | public class Hsmap { | 
hashmap

LinkedHashMap

因为有双项链表所以才有序
TreeMap
可定义key的排序规则,自动升序。
可变参数
| 1 | void (int a,int... args) | 
可变参数一定要写在最后。
初识线程

线程是抢占式调度
线程优先级只是一个概率大小的问题
守护线程,是其他线程结束后,才会陆陆续续的结束的线程(不是立马停止
礼让线程,类名.方法,让出当前CPU尽可能让线程执行均匀(了解即可

很重要的一张图
线程安全性
线程执行时,具有随机性,在当前线程执行时,cpu的执行权很可能被其他线程给抢走。(特别是对于共享代码块)

锁机制就是一种常用的同步机制,它可以用来保护共享资源,确保在某个线程访问共享资源时,其他线程无法同时修改该资源,从而保证数据的一致性。通过加锁,我们可以控制多线程对共享资源的访问顺序和互斥性,避免竞争条件的发生。
加锁并不意味着多线程失去了意义。相反,合理地使用锁可以解决线程间的竞争问题,保证数据的正确性,并发执行的优势依然存在。锁的作用是提供了一种同步机制,使得多线程能够协调地访问共享资源,确保线程间的互斥和顺序性,从而避免数据的混乱和冲突。
synchronized ()
检测到线程进来自动的关锁,线程执行完又自动的开锁。
同步代码块
就是把一段共享代码块锁起来,这样可以避免共享数据时的抢占安全性问题。
如果把整个方法里的代码全部锁起来就不用在代码块外面包裹synchronized (){}了直接在方法外面锁。
同步方法

Lock
手动开锁和关锁。
关于死锁:切记不要让两个锁嵌套起来。
生产者和消费者(等待唤醒机制)


线程四步走

阻塞队列



线程池

自定义线程池
需要的7个参数

核心线程都在忙,排核心线程的队已经排满,这个时候才创建临时线程。


网络编程


会出现ip不够用
所以有了ipv6


节省ipv4的方式

在每个地方的局域网,都可能碰上不一样的路由给我的电脑分配不一样的ip地址,向一个ip发送消息是限制地方的。如果向该ip地址发送一些消息,如下:

但是localhost:(127.0.0.1)是一个特殊地址,是一个本地回环地址,即为本机ip。此时发送消息时不经过路由器的。所以向这个ip发送东西不限制地方。如下:




UDP通信协议
