CoreJava 笔记总结-第六章 接口、lambda表达式与内部类

文章目录

  • 第六章 接口、lambda表达式与内部类
    • ==接口==
      • 接口的概念
      • 接口的属性
      • 接口与抽象类
      • 静态和私有方法
      • 默认方法
      • 解决默认方法冲突
      • 接口与回调
      • `Comparator`接口
      • 对象克隆
    • ==`lambda`表达式==
      • ==函数式接口==
      • 方法引用
      • 构造器引用
      • 变量作用域
      • 处理`lambda`表达式
      • 再谈`Comparator`类
    • 内部类
      • 使用内部类访问对象的状态
      • 局部内部类
      • 由外部方法访问变量
      • 匿名内部类
      • 静态内部类
    • 代理
      • 何时使用代理
      • 创建代理对象
      • 代理的特性

第六章 接口、lambda表达式与内部类

  • 接口: 描述类应该做什么, 不指定如何做
  • lambda表达式: 表示使用回调或者可变行为的代码

接口

接口的概念

  • 接口: 不是类, 而是对希望符合这个接口的类的一组需求

  • Arrays类中的sort方法对对象数组进行排序, 要求对象所属的内必须实现Comparable接口

public interface Comparable
{int compareTo(Object other);
}
//java5后
public interface Comparable<T>
{int compareTo(T other);
}
  • 接口中的所有方法自动为public
  • 接口中可以包含多个方法, 但是接口不会有实例字段
  • 让一个类实现一个接口:
    1. 将类声明为实现给定的接口
    2. 对接口中的所有方法提供定义
  • 将类声明为实现为某个接口, 使用关键字implements
class Employee implements Comparable
  • Java API建议equals, compareTo方法兼容
  • 例外:x = BigDecimal("1.0"); y = BigDecimal("1.00"); x.equals(y)//false x.compareTo(y) == 0
package chapter6_interface_lambda_innerClass.interfaces;public class Employee implements Comparable<Employee>{private String name;private double salary;public Employee(String name, double salary) {this.name = name;this.salary = salary;}public double getSalary() {return salary;}public String getName() {return name;}public int compareTo(Employee other) {return Double.compare(salary, other.salary);}
}package chapter6_interface_lambda_innerClass.interfaces;import java.util.Arrays;public class EmployeeSortTest {public static void main(String[] args) {var staff = new Employee[3];staff[0] = new Employee("Oukunnan", 25598);staff[1] = new Employee("Ovfdunnan", 18);staff[2] = new Employee("dsukunnan", 98);Arrays.sort(staff);for (Employee employee : staff) {System.out.println(employee.getName() + "  salary=" + employee.getSalary());}}
}

接口的属性

  • 接口不是类, 不能用new运算符实例化一个接口
  • 能够声明接口变量: Comparable x ; //OK
  • 接口变量必须引用实现了这个接口的类对象 x = new Employee(...);
  • instanceof: 1. 检查一个对象是否属于某个特定的类 2. 一个对象是否实现了某个特定的接口
if (anObject instanceof Comparable){...};
  • 与建立类的继承层次类似, 可以扩展接口
public interface Moveable{...}
public interface Powered extends Moveable{..}
  • 接口不能包含实例字段但是可以包含常量
  • 接口的方法总是public, 接口的字段总是public static final, 都可以省略, 建议省略
  • 每个类只有一个超类, 却可以实现多个接口, 有点像C++的多重继承

接口与抽象类

  • 抽象类问题: 每个类只能扩展一个类
  • java可以扩展一个基类并且派生多个接口

静态和私有方法

  • 标准库中成对出现的接口和实用工具类: Collection/Collections, Path/paths
  • 允许在接口中增加静态方法, 一般做法是放在伴随类中
  • java9中接口中的方法可以是private

默认方法

  • 接口方法提供一个默认实现, default修饰符标记
public interface Comparable<T>
{default int CompareTo(T other) {return 0;}
}
  • 如果迭代器是只读的就不用实现remove方法

    public interface Iterator<E>
    {boolean hasNext();E next();default void remove(){throw new UnsupprotedOperationException("remove");}
    }
    
  • 另一个作用是接口演化, 实现源代码兼容


解决默认方法冲突

  • 超类优先
  • 同时实现的两个接口中由完全同名并且参数类型相同的方法, 要求这个类实现该方法覆盖接口的方法
  • class Student extends Person implements Named{...}只会考虑超类方法, 类优先原则

接口与回调

  • 回调: 指定某个特定事件发生时应该采取的动作
package chapter6_interface_lambda_innerClass.timer;import java.awt.event.*;
import java.awt.*;
import java.time.*;
import javax.swing.*;public class TimerTest {public static void main(String[] args) {var listener = new TimePrinter();var timer = new Timer(1000, listener);//每隔1000ms(1s)响铃并且打应输出timer.start();JOptionPane.showMessageDialog(null, "Quit Program?");//展示消息框System.exit(0);}
}class TimePrinter implements ActionListener {public void actionPerformed(ActionEvent event) {//ActionEvent 事件参数,提供事件的相关信息              //getWhen的得到纪元以来的毫秒数, 利用函数转换成可读时间System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));Toolkit.getDefaultToolkit().beep(); //调用默认工具箱响铃}
}

Comparator接口

  • 对于对象数组进行排序, 前提是这些对象是实现了Comparable接口类的实例
  • 如果按照长度而不是字典顺序对于字符串进行排序, 使用Arrays.sort的另一种版本, 一个数组和比较器作为参数
  • 比较器实现Comparator接口
public interface Comparator<T>
{int compare(T first, T second);
}class LengthComparator implements Comparator<String>
{public int compare(String first, String second){return first.length() - second.length();}
}调用
Arrays.sort(words, new LengthComparator());

对象克隆

  • 拷贝: 一个包含对象引用的变量建立副本时,原变量和副本都是对同一个对象的引用, 任何一个对象的引用都会改变另一个变量
  • 克隆: 希望变量是一个新的对象, 初始状态和原变量相同, 之后会有各自不同的状态
  • 默认的克隆操作是浅拷贝: 逐个字段拷贝, 对于数值和其他基本类型克隆, 但是对于包含对象引用的子对象也会共享一些信息
  • 如果原对象和浅克隆对象共享的子对象是不可变的, 那么浅拷贝的共享安全
  • 深拷贝: 子对象可变的, 必须重新定义clone方法建立深拷贝, 克隆所有对象
  • Cloneable: 标记接口, 不包含任何方法(一般的接口确保一个类实现一组特定的方法), 作用:允许类型查询中使用instanceof
if(obj instanceof Cloneable) ...
  • 所有数组类型都有一个公共的clone方法, 不是受保护的
int[] a = {1, 2, 3};
int[] b = a.clone();
b[0] = 5;// a[0] == 1;
package chapter6_interface_lambda_innerClass.clone;public class CloneTest {public static void main(String[] args) throws CloneNotSupportedException{var original = new Employee("Ou Kunnan", 52000);original.setHireDay(2001, 12, 26);Employee copy = original.clone();System.out.println(copy); // 自动调用toString方法,相当于copy.toString()copy.raiseSalary(10);copy.setHireDay(2002, 12, 26);System.out.println("original: " + original);System.out.println("copy: " + copy);}
}package chapter6_interface_lambda_innerClass.clone;import java.util.Date;
import java.util.GregorianCalendar;public class Employee implements Cloneable{private double salary;private String name;private Date hireDay;public Employee(String name, double salary) {this.name = name;this.salary = salary;hireDay = new Date();}public Employee clone() throws CloneNotSupportedException {Employee cloned = (Employee) super.clone();cloned.hireDay = (Date) hireDay.clone();return cloned;}public void setHireDay(int year, int month, int day) {Date newHireDay = new GregorianCalendar(year, month - 1, day).getTime();hireDay.setTime(newHireDay.getTime());}public void raiseSalary(double byPercent) {double raise = salary * byPercent / 100;salary += raise;}public String toString() {return "Employee[name=" + name + ", salary=" + salary + ", hireDay=" + hireDay + "]";}
}

lambda表达式

  • lambda表达式就是一个代码块,以及必须传入的代码变量规范

  • 形式: 参数, ->, 一个表达式

  • (String first, String second)->{if(first.length()  < second.length()) return -1;else return 1;
    }
    
  • lambda没有参数,`()-> {…};

  • 如果可以推导出lambda表达式参数类型, 可以忽略其类型

Comparator<String> comp = (first, second) -> first.length() - second.length();
  • 只有一个参数并且类型可以推到, 可以省略小括号

  • 无需指定返回类型

package chapter6_interface_lambda_innerClass.lambda;import java.util.*;import javax.swing.*;
import javax.swing.Timer;public class lambdaTest {public static void main(String[] args) {var planets = new String[]{"Mercury", "Venus", "Earth", "Mars","Jupiter", "Saturn", "Uranus", "Neptune"};System.out.println(Arrays.toString(planets));System.out.println("Sorted in dictionary order:");Arrays.sort(planets);System.out.println(Arrays.toString(planets));System.out.println("Sorted by length:");Arrays.sort(planets, (first, second) -> first.length() - second.length());//第二个参数应该是比较器System.out.println(Arrays.toString(planets));var timer = new Timer(1000, event -> System.out.println("The time is " + new Date()));timer.start();JOptionPane.showMessageDialog(null, "quit?");System.exit(0);}
}

函数式接口

  • 函数式接口: 对于只有一个抽象方法的接口,需要这种接口对象时, 可以提供一个lambda表达式
  • lambda表达式可以转换为接口
var timer = new Timer(1000, event->{System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));Toolkit.getDefaultToolkit().beep(); })
  • ArrayList类的removeIf方法参数是Predicate
public interface Predicate<T>
{boolean test(T t);
}
//删除列表所有null值
list.removeIf(e -> e == null);
  • supplier没有参数, 调用时会生成T类型的值, 用于实现计算
public interface Supplier<T>
{T get();
}LocalDate hireDay = Objects.requireNonNullOrElse(day, new LocalDate(1970, 1, 1));//通过使用供应者supplier, 延迟该计算 , 只有day==null时候才调用供应者(构造默认的LocalDate)
LocalDate hireDay = Objects.requireNonNullOrElse(day, () -> new LocalDate(1970, 1, 1));

方法引用

  • var timer = new Timer(1000, event->System.out.println(event));
    var timer = new Timer(1000, System.out::println);
    
  • System.out::println是一个方法引用, 它指示编译器生成一个函数式接口的实例,覆盖这个接口的抽象方法来调用给定的方法

  • 上面的例子, 会生成一个ActionListener, 他的actionPerformed(ActionEvent e)方法要调用System.out.println(e)

  • 方法引用不是对象, 为一个类型为函数式接口的变量赋值时会生成一个对象

  • 方法引用示例与等价的lambda表达式见P248

  • 当lambda表达式的体只调用一个方法而不做其他操作的时候才能把方法引用重写为方法引用


构造器引用

  • Person::new就是Person构造器的一个引用
  • int[]::new是一个构造器引用, 他有一个参数,即数组的长度, 等价于x->new int[x]

变量作用域

  • lambda表达式三个部分: 代码块, 参数, 自由变量的值
  • 可以把一个lambda表达式转换为一个包含方法的对象, 自由变量的值会复制到这个对象的实例变量中
  • lambda表达式是闭包的
  • lambda表达式可以捕获外围作用域中变量的值, 确保值是明确定义的(事实最终变量, 初始化后不会改变)

处理lambda表达式

  • lambda表达式重点是延迟执行

  • Runnable作为无参数或返回值的动作运行, action.run()会调用lambda表达式主体

    package test;import java.util.function.IntConsumer;public class lambda {public static void main(String[] args){repeat(10, ()->System.out.println("hello, world"));repeat(10, (i)->System.out.println("Countdown:" + (9-i)));}public static void repeat(int n, Runnable action){for(int i = 0; i < n; i++) action.run();}public static void repeat(int n, IntConsumer action) {for(int i = 0; i < n; i++)action.accept(i);}
    }
    

再谈Comparator

  • P255

内部类

  • 定义在另一个类中的类
  • 内部类可以对同一个包中的其他类隐藏, 内部类方法可以访问定义这个类的作用域中的数据,包括原本的私有数据

使用内部类访问对象的状态

  • 一个内部类方法可以访问自身的数据字段,也可以访问创建它的外围类对象的数据字段
  • 内部类对象总有一个隐式引用指向创建它的外部类对象
  • 这个引用在构造器中设置, 编译器会修改所有内部类的构造器,添加一个对应外围类引用的参数
以下这个例子生成的无参数构造器如下
public TimePrinter(TalkingClock clock){outer = clock;}
package chapter6_interface_lambda_innerClass.innerClass;
import java.awt.*;
import java.awt.event.*;
import java.time.*;import javax.swing.*;public class innerClassTest {public static void main(String[] args) {var clock = new TalkingClock(1000, true);clock.start();JOptionPane.showMessageDialog(null, "Quit?");System.exit(0);}
}class TalkingClock{private int interval;private boolean beep;public TalkingClock(int interval, boolean beep) {this.interval = interval;this.beep = beep;}public void start() {var listener = new TimerPrinter();var timer = new Timer(interval, listener);timer.start();}public class TimerPrinter implements ActionListener {public void actionPerformed(ActionEvent event) {System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));if (beep) {Toolkit.getDefaultToolkit().beep();}}}}

局部内部类

  • TimePrinter名字只出现了一次,在start方法中创建这个类型对象时使用了一次.可以在一个方法中局部定义这个类

    public void start() {class TimerPrinter implements ActionListener {public void actionPerformed(ActionEvent event) {System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));if (beep) {Toolkit.getDefaultToolkit().beep();}}}var listener = new TimerPrinter();var timer = new Timer(interval, listener);timer.start();
    }
    
  • 局部内部类声明时候不能有访问修饰符public, private

  • 优势: 对外部完全隐藏,除了start代码


由外部方法访问变量

  • 局部内部类不仅能够访问外部类字段,还可以访问局部变量(事实最终变量)

  • public void start(int interval, boolean beep) {class TimerPrinter implements ActionListener {public void actionPerformed(ActionEvent event) {System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));if (beep) {Toolkit.getDefaultToolkit().beep();}}}var listener = new TimerPrinter();var timer = new Timer(interval, listener);timer.start();
    }
    

匿名内部类

  • 匿名内部类不需要为类指定名字

  • 以下代码: 创建了一个类的新对象,这个类实现了ActionListener接口, 需要实现的方法{}中定义

    public void start(int interval, boolean beep) {var listener = new ActionListener();{public void actionPerformed(ActionEvent event) {System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));if (beep) {Toolkit.getDefaultToolkit().beep();}}};var timer = new Timer(interval, listener);timer.start();
    }//用lambda表达式
    public void start(int interval boolean beep)
    {var timer = new Timer(interval, event->{System.out.println("At this tone, the time is " + Instant.ofEpochMilli(event.getWhen()));if (beep) Toolkit.getDefaultToolkit().beep();})
    }
    
  • 语法如下

new SuperType(construction parameters)
{innner class methods and data
}

SuperType可以是接口,内部类就要实现这个接口;如果是一个类,内部类就要扩展这个类

  • 构造器名字必须和类名相同,匿名内部类没有类名所以没有构造器
  • 构造参数要传递给超类构造器
  • 注意: 构造一个类的新对象和构造一个扩展了那个类的匿名内部类的对象之间的差别
vae queen = new Person("Marry");
var count = new Person("bjcs"){...};
  • 匿名内部类不能有构造器但是可以提供一个对象的

  • 双括号初始化:

  • var f  = new ArrayList<String>();
    f.add("Harry");
    f.add("Alice");
    invite(f);
    --->
    invite(new ArrayList<String>)(){{add("Harry"); add("Alice");}}  
    //外层括号建立了一个匿名子类,内层括号是一个初始化块
    
  • 得到匿名内部类的外部类类名不能直接getClass,这个方法带调用this.getClass(), 静态方法没有隐式参数

new Object(){}.getClass().getEnclosingClass()

new Object()建立Object的匿名子类的一个匿名对象,getEnclosingClass则得到其外围类,也就是包含这个静态方法的类


静态内部类

  • 只要内部类不需要访问外围类对象,就应该使用静态内部类
  • 接口中声明的内部类自动为public, static
package chapter6_interface_lambda_innerClass.staticInnerClass;public class StaticInnerClassTest
{public static void main(String[] args){var values = new double[20];for (int i = 0; i < values.length; i++)values[i] = 100 * Math.random();ArrayAlg.Pair p = ArrayAlg.minmax(values);System.out.println("min = " + p.getFirst());System.out.println("max = " + p.getSecond());}
}class ArrayAlg{public static class Pair {/* 一个静态的内部类 */private double first;private double second;/*** Constructs a pair from two floating-point numbers** @param f the first number* @param s the second number*/public Pair(double f, double s) {first = f;second = s;}/*** Returns the first number of the pair** @return the first number*/public double getFirst() {return first;}/*** Returns the second number of the pair** @return the second number*/public double getSecond() {return second;}}/*** Computes both the minimum and the maximum of an array* @param values an array of floating-point numbers* @return a pair whose first element is the minimum and whose second element* is the maximum*/public static Pair minmax(double[] values){double min = Double.POSITIVE_INFINITY;double max = Double.NEGATIVE_INFINITY;for (double v : values) {if (min > v) {min = v;}if (max < v) {max = v;}}return new Pair(min, max);}
}

代理

何时使用代理

  • 代理类在运行时闯将全新的类,这样代理类可以实现你指定的接口
  • 代理类包含的方法: 指定接口所需要的全部方法, Object类中的全部方法(equals, toStirng等)

创建代理对象

  • 需要使用Proxy类的newProxyInstance方法, 有三个参数
    • 一个类加载器(这里指定系统类加载器)
    • 一个Class对象数组,每个元素对应需要实现的各个接口
    • 一个调用处理器
  • 代理作用: 将方法调用路由到远程服务器;在运行中的程序将用户界面事件与动作关联起来;为了调试,跟踪方法使用
package chapter6_interface_lambda_innerClass.proxy;import java.lang.reflect.*;
import java.util.*;public class ProxyTest
{public static void main(String[] args) {var elements = new Object[1000];for (int i = 0; i < elements.length; i++) {Integer value = i + 1;var handler = new TraceHandler(value);Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),new Class[]{Comparable.class}, handler);elements[i] = proxy;}Integer key = new Random().nextInt(elements.length) + 1;int result = Arrays.binarySearch(elements, key);if(result >= 0) System.out.println(elements[result]);}
}class TraceHandler implements InvocationHandler {//打应输出方法名和参数,并且调用该方法private Object target;public TraceHandler(Object t) {target = t;}public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {System.out.print(target);System.out.print("." + m.getName() + "(");if (args != null) {for (int i = 0; i < args.length; i++) {System.out.print(args[i]);if(i < args.length - 1) System.out.print(", ");}}System.out.println(")");return m.invoke(target, args);}
}

代理的特性

  • 代理是在运行过程中创建的,一旦创建就变成了常规类
  • 代理类都是扩展Proxy, 一个代理类只有一个实例字段即调用处理器,在超类Proxy中定义
  • 所有的代理类都要覆盖toString, hasCode, equals方法, 这些方法只是在调用处理器上调用invoke.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311383.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【复杂系统迁移 .NET Core平台系列】之静态文件

源宝导读&#xff1a;微软跨平台技术框架—.NET Core已经日趋成熟&#xff0c;已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。一、背景随着ERP的产品线越来越多&#xff0c;业务关联也日益复杂&#xff0c;…

[Abp vNext 源码分析] - 19. 多租户

一、简介ABP vNext 原生支持多租户体系&#xff0c;可以让开发人员快速地基于框架开发 SaaS 系统。ABP vNext 实现多租户的思路也非常简单&#xff0c;通过一个 TenantId 来分割各个租户的数据&#xff0c;并且在查询的时候使用统一的全局过滤器(类似于软删除)来筛选数据。关于…

HTMLCSS 超简单的前端设计入门-2!

文章目录图片元素img元素和a元素连用和map元素和figure元素多媒体元素videoaudio列表元素有序列表无序列表定义列表容器元素div元素语义化容器元素元素包含关系为网页添加样式CSS术语解释选择器声明块CSS代码书写位置常见样式声明选择器简单选择器选择器的组合选择器的并列层叠…

八数码问题I-bfs和map标记

解题思路&#xff1a; bfs&#xff0c;将棋盘转化成一个整数表示其状态&#xff0c;比如我们到到达的状态是815736402&#xff0c;而样例给的输入状态是264137058&#xff0c;因为这些整数过大&#xff0c;标记数组开不下&#xff0c;所以可以用map来代替数组&#xff0c;写得时…

一个迷你ASP.NET Core框架的实现(下)

【框架内幕】| 作者 / Edison Zhou这是恰童鞋骚年的第196篇原创文章上一篇我们了解了AspNetCore.Mini这个项目的背景及项目结构和流程&#xff0c;这一篇我们继续解析几个核心对象。本文整理自A大&#xff08;蒋金楠&#xff09;的主题分享&#xff0c;点击本文底部“阅读原文”…

CoreJava 笔记总结-第七章 异常,断言和日志

文章目录第七章 异常,断言和日志处理错误异常的分类声明检查型异常如何抛出异常创建异常类捕获异常捕获单个异常捕获多个异常再次抛出异常和异常链finally子句try-with-Resource语句分析堆栈轨迹元素使用异常的技巧使用断言使用断言完成参数检查日志基本日志高级日志调试技巧第…

根据后序和中序求二叉树的先序

代码如下&#xff1a; #include <iostream> using namespace std; const int N 1010; int in_order[N], post_order[N], lch[N], rch[N];int build(int inL, int inR, int postL, int postR) {if (inL > inR)return 0;int root post_order[postR];int k inL;while…

CoreJava 笔记总结-第九章 集合

第九章 集合 文章目录第九章 集合Java集合框架集合接口与实现分离Collection接口迭代器泛型实用方法集合框架中的接口具体集合链表数组列表散列集树集优先队列映射映射的基本操作更新映射条目映射视图弱散列试图链接散列集与映射枚举集与映射标识散列映射视图与包装器小集合子范…

30多岁程序员老W,无奈选择转行!问题出在哪?

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区特邀嘉宾&#xff01;一有一天&#xff0c;一位同事跟我说&#xff1a;老w已经改行做美缝去了&#xff0c;你怎么看&#xff1f;我想了想&#xff0c;说&#xff1a;他大概终于做出了眼下最符合他…

一维前缀和

代码如下&#xff1a; #include <iostream> using namespace std; const int N 1010; int a[N], s[N];int main() {int n;cin >> n;for (int i 1; i < n; i) {cin >> a[i];//原数组s[i] s[i - 1] a[i];}for (int i 1; i < n; i)cout << s[…

HttpClientFactory的套路,你知多少?

背景ASP.NET Core 在 2.1 之后推出了具有弹性 HTTP 请求能力的 HttpClient 工厂类 HttpClientFactory。替换的初衷还是简单摆一下&#xff1a;① using(var client new HttpClient()) 调用的 Dispose() 方法并不会立即释放底层 Socket 连接&#xff0c;新建 Socket 需要时间&a…

CoreJava 笔记总结-第十二章 并发-1

第十二章 并发 线程 package chapter12_concurrent.threads;public class ThreadsTest {public static final int DELAY 10;public static final int STEPS 100;public static final double MAX_AMOUNT 1000;public static void main(String[] args) {var bank new Bank(…

走迷宫-双向bfs解法

双向bfs适用于知道起点和终点的状态下使用&#xff0c;从起点和终点两个方向开始进行搜索&#xff0c;可以非常大的提高单个bfs的搜索效率同样&#xff0c;实现也是通过队列的方式&#xff0c;可以设置两个队列&#xff0c;一个队列保存从起点开始搜索的状态&#xff0c;另一个…

.NET Core开发实战(第16课:选项数据热更新:让服务感知配置的变化)--学习笔记...

16 | 选项数据热更新&#xff1a;让服务感知配置的变化选项框架还有两个关键类型&#xff1a;1、IOptionsMonitor2、IOptionsSnapshot场景&#xff1a;1、范围作用域类型使用 IOptinsSnapshot2、单例服务使用 IOptionsMonitor通过代码更新选项&#xff1a;IPostConfigureOption…

CoreJava 笔记总结-第十二章 并发-2

文章目录第十二章 并发synchronized关键字同步块监视器概念volatile字段final变量原子性死锁线程安全的集合阻塞队列映射条目的原子更新对并发散列映射的批操作并行数组算法同步包装器任务和线程池Callable, FutureExecutor执行器fork-in框架异步计算可完成Future组合可完成Fut…

八数码问题II-bfs和map标记

问题描述&#xff1a; 在33的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字。棋盘中留有一个空格&#xff0c;空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a; 给出一种初始布局&#xff08;初始状态&#xff09;和目标布…

华为任职资格_看了华为的任职资格体系,你就明白员工为啥这么拼?

提到华为的18万奋斗者&#xff0c;职场上没人不竖起大拇指。而优秀人才的背后&#xff0c;就像任正非曾说过的那样&#xff0c;华为的成功&#xff0c;很大意义上讲就是人力资源的成功。华为的人力资源管理最有代表性的&#xff0c;除了狼性文化和薪酬绩效外&#xff0c;就是任…

如何使用有序GUID提升数据库读写性能

源宝导读&#xff1a;数据库设计时&#xff0c;经常会使用GUID作为表的主键&#xff0c;但由于GUID的随机性会导致数据库在读写数据时效率严重下降&#xff0c;影响应用程序整体性能。本文将深入探讨如何通过使用有序GUID提升数据读写的性能。一、背景常见的数据库设计是使用连…

八数码问题II-双向bfs和map标记

问题描述&#xff1a; 在33的棋盘上&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字。棋盘中留有一个空格&#xff0c;空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是&#xff1a; 给出一种初始布局&#xff08;初始状态&#xff09;和目标布…

MarkDown语法, 快捷键,Dos命令

文章目录MarkDown 语法计算机软件快捷键Dos命令MarkDown 语法 字体: 斜体, 粗体, 删除图片: ![title](link)超链接: [words](link)引用>标题列表表格 名字|性别|生日 31辅导班VS看复旦南开都是vs1ds代码块 分割线*** 计算机软件 系统软件应用软件DOS, Windows, Unix,…