不可变集合
什么是不可变集合
就是不可修改的集合。集合的数据在创建的时候提供,并且在整个生命周期都不可改变,否则报错。
问:为什么需要创建不可变集合
答:如果某个数据不能被修改。
public class Demo1 {
public static void main(String[] args) {
List<Double> lists = List.of(23.2,53.6,36.1);
//.lists.set(1,99.9);UnsupportedOperationException
System.out.println(lists);
System.out.println(lists.get(2));
Set<String> sets= Set.of("da","sad","dw");
//sets.add("html");
System.out.println(sets);
Map<String,Integer> map =Map.of("shouji",53,"shoubiao",1);
System.out.println(map);
}
}
上述方法同样存在set和map集合中
public static void main(String[] args) {
// 1 创建不可变集合
List<Double> lists = List.of(23.2,53.6,36.1);
//集合创建之后 不允许添加和修改元素 但是可以通过获取的方式 获取其中的元素
//lists.add(78.9);
//lists.set(1,99.9);//UnsupportedOperationException
System.out.println(lists);
System.out.println(lists.get(2));
Set<String> sets = Set.of("java","mysql","css");
//sets.add("html");
System.out.println(sets);
Map<String,Integer> map = Map.of("手机",1,"手表",5);
System.out.println(map.get("手表"));
}
Stream流
什么是Stram流
在Java8中,引入lambda表达式,带来函数式编程,引入了一个全新的Stream流概念。
问:为什么要存在呢?
答:简化集合和数组的操作。
public class StreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张三丰");
list.add("张强");
// 把集合中所有以”张“开头的元素存储到一个新的集合。
//把张开头的集合中的长度为3的元素存储到一个新的集合
//遍历上一步得到的集合中的元素
List<String> zhangList = new ArrayList<>();
for (String name:list){
if(name.startsWith("张")){
zhangList.add(name);
}
}
System.out.println(zhangList);
List<String> zhang3List = new ArrayList<>();
for (String n:zhangList){
if(n.length() == 3){
zhang3List.add(n);
}
}
System.out.println(zhang3List);
System.out.println("-----------------------------");
//使用Stream实现
// list.stream().filter(new Predicate<String>() {
// @Override
// public boolean test(String s) {
// return s.startsWith("张");
// }
// }).forEach(s -> System.out.println(s));
list.stream().filter(s->s.startsWith("张")).filter(s-
>s.length()==3).forEach(s->System.out.println(s));
}
}
Stream的核心思想:
1 先得到集合或者数组的Stream流对象。
2 把元素放进去
3 然后用Stream流简化的ApI来操作元素
Stream流的获取
Straem流的三类方法
- 获取Straem流
- 中间方法
- 终结方法
获取Straem流方式:
可以使用Collection接口中的默认方法 stream()获取
default Stream stream() 返回以此集合为源的顺序 Stream 。
数组获取方式:
通过Arrays工具类中提供的方法
Map集合
是间接的通过keySet 或者entitySet来进行流的操作。
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
Stream<String> s= c.stream();
Map<String,Integer> map = new HashMap<>();
// 键的stream流
Stream<String> keyStream = map.keySet().stream();
//值流
Stream<Integer> valStream = map.values().stream();
// 键值对流
Stream<Map.Entry<String,Integer>> entryStream = map.entrySet().stream();
String[] names = {"张三","里斯"};
Stream<String> arrStream = Arrays.stream(names);
Stream<String> arrStream2 = Stream.of(names);
}
##2.3常用API
Stream的综合应用需求: 某公司的研发部门,分为研发一部和二部,现在需要进行年终数据结算
要求:
1 员工信息至少包含(名称 性别 工资 奖金 处罚记录)
2 开发一部有4个员工,二部有5个员工
3 分别筛选2个部门的最高工资的员工信息,封装成优秀员工对象
4 分别统计2个部门的平均月收入,要求去掉最高工资和最低工资
5 统计2个部门的整体的平均工资,去掉最高工资和最低工资
public class Employee {
private String name;
private char sex;
private double salary;
private double bonus;
private String punish;
public Employee() {
}
public Employee(String name, char sex, double salary, double bonus, String
punish) {
this.name = name;
this.sex = sex;
this.salary = salary;
this.bonus = bonus;
this.punish = punish;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public String getPunish() {
return punish;
}
public void setPunish(String punish) {
this.punish = punish;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return sex == employee.sex && Double.compare(employee.salary, salary) ==
0 && Double.compare(employee.bonus, bonus) == 0 && Objects.equals(name,
employee.name) && Objects.equals(punish, employee.punish);
}
@Override
public int hashCode() {
return Objects.hash(name, sex, salary, bonus, punish);
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", sex=" + sex +
", salary=" + salary +
", bonus=" + bonus +
", punish='" + punish + '\'' +
'}';
}
}
//优秀员工
public class TopperEmp {
private String name;
private double money;
public TopperEmp() {
}
public TopperEmp(String name, double money) {
this.name = name;
this.money = money;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TopperEmp topperEmp = (TopperEmp) o;
return Double.compare(topperEmp.money, money) == 0 &&
Objects.equals(name, topperEmp.name);
}
@Override
public int hashCode() {
return Objects.hash(name, money);
}
@Override
public String toString() {
return "TopperEmp{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
}
public class StreamDemo3 {
private static double allMoney1;
private static double allMoney2;
public static void main(String[] args) {
List<Employee> oneEmps = new ArrayList<>();
oneEmps.add(new Employee("孙悟空",'男',5000,1000,null));
oneEmps.add(new Employee("八戒",'男',3000,100,"顶撞上司"));
oneEmps.add(new Employee("沙僧",'男',2000,50,"迟到早退"));
oneEmps.add(new Employee("唐僧",'男',10000,3000,null));
List<Employee> twoEmps = new ArrayList<>();
收集Stream流
收集Stream流的作用:就是把Stream流操作后的结果转回到集合或者数组中去。
Stream流:操作集合/数组的手段
集合/数组:才是目的。
Stream流的收集的方法:
<R,A>R
collect(Collector<? super T,A,R>collector)
开始收集Stream流,指定收集器
Collectors工具类 提供了收集的方式
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张三丰");
list.add("张三丰");
list.add("张强");
Stream<String> s1 = list.stream().filter((s->s.startsWith("张")));
// 将处理之后的流收集成一个集合
List<String> zhangList = s1.collect(Collectors.toList());//可变集合
zhangList.add("java");
System.out.println(zhangList);
// 注意 “流只能使用一次”
Stream<String> s2 = list.stream().filter((s->s.startsWith("张")));
Set<String > zhagSet = s2.collect(Collectors.toSet());
System.out.println(zhagSet);
// Object[] arr = s2.toArray();
// System.out.println(arr);
}
Java中的Stream是一种用于处理集合数据的API,它提供了一种函数式编程的方式来处理数据。Stream可以对集合中的元素进行过滤、映射、排序、聚合等操作,而这些操作都可以通过链式调用来实现。Stream的使用可以大大简化代码,提高代码的可读性和可维护性。
日志框架
日志框架概述
作用:记录程序运行过程中的信息,并可以永久进行保存输出打印到控制台:
弊端:
- 信息只能展示在控制台不能记录到其他位置
- 想要取消记录的信息需要修改代码才可以完成
日志技术的体系结构
日志规范接口: Commons loging (gcl)/Simple Loging factory for java(slf4g)
日志实现框架:log4j、logback
Logback
Logback是基于slf4j规范的实现框架
Logback主要分为三大模块
Logback-core:该模块提供Logback的最核心功能为其他的两大模块奠定基础
Logback-classsic:是logf4j的一个改良版本,完整的实现了slf4j api
Logback-access:该模块与tomcat和jetty等Service容器的继承,提供了Http的访问日志功能
Logback使用
- 项目中新建一个目录lib,导入相关jar文件到项目中去
- 配置logback
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--
CONSOLE :表示当前的日志信息是可以输出到控制台的。
-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--输出流对象 默认 System.out 改为 System.err-->
<target>System.out</target>
<encoder>
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽
度
%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] :
%msg%n</pattern>
</encoder>
</appender>
<!-- File是输出的方向通向文件的 -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}
- %msg%n</pattern>
<charset>utf-8</charset>
</encoder>
<!--日志输出路径-->
<file>D:/code/logback-data.log</file>
<!--指定日志文件拆分和压缩规则-->
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--通过指定压缩文件名称,来确定分割文件方式-->
<fileNamePattern>D:/code/logback-data-%d{yyyyMMdd}.log%i.gz</fileNamePattern>
<!--文件拆分大小-->
<maxFileSize>1MB</maxFileSize>
</rollingPolicy>
</appender>
<!--
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
, 默认debug
<root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
-->
<root level="ALL">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE" />
</root>
</configuration>
- 在代码中获取日志对象
Logger logger = LoggerFactory.getLogger(“类对象”);
public static void main(String[] args) {
//日志的级别 Trace<Debug<Info
// all 打开所有的日志信息
//off 关闭所有的日志信息
Logger logger = LoggerFactory.getLogger(LogDemo1.class);
logger.info("这是一个info级别的日志");
logger.debug("这是一个debug级别的日志");
logger.trace("这是一个trace级别的日志");
}
日志的级别的设置:
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
, 默认debug
<root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
-->
<root level="TRACE">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE" />
</root>
</configuration>
值输出级别不低于设定级别的日志信息。