初识Java 12-2 流

目录

中间操作

跟踪与调试

对流元素进行排序

移除元素

将函数应用于每个流元素

在应用map()期间组合流

Optional类型

便捷函数

创建Optional

Optional对象上的操作

由Optional组成的流


本笔记参考自: 《On Java 中文版》


中间操作

||| 中间操作:从流中接收一个对象,并将对象作为另一个流送出后端,以连接其他操作。

跟踪与调试

        peek()操作是用于辅助调试的,它允许我们查看流对象而不修改它。

【例子:peek()的使用流】

public class Peeking {public static void main(String[] args)throws Exception {FileToWords.stream("Cheese.dat").skip(21).limit(4).map(w -> w + " ").peek(System.out::print) // 查看当前流的状态.map(String::toUpperCase).peek(System.out::print).map(String::toLowerCase).forEach(System.out::print);}
}

        程序执行的结果是:

        其中,FileToWords类的形式如下(之后会再展示):

这个类的作用就是生成一个String对象组成的流。

        当流在管线中传输时,我们使用了peek()进行观察。这里要注意的是,peek()接受的是一个遵循Consumer函数式接口的函数:

这样的函数没有返回值Consumer一般用于对输入元素进行消费),所以也就不可能使用不同的对象替换流中的对象。因此我们只能“观察”这些对象。


对流元素进行排序

        sorted()方法可用于流的排序,它有一种可以接受一个Comparator参数的形式:

【例子:接受参数的sorted()

import java.util.Comparator;public class SortedComparator {public static void main(String[] args)throws Exception {FileToWords.stream("D:\\code\\Java\\Test_Java\\src\\streams\\Cheese.dat").skip(10).limit(10).sorted(Comparator.reverseOrder()).map(w -> w + " ").forEach(System.out::print);System.out.println();}
}

        程序执行的结果是:

        也可以传入一个lambda表达式作为sorted()的参数,不过也有许多预设的Comparator


移除元素

        介绍两个用于从流中移除元素的操作:

  • distinct():可用于移除流中的重复元素。与Set相比,distinct()要更加简洁。
  • filter(Predicate):过滤,只保留符合特定条件(结果为true)的元素。

        distinct()在笔记12-1的Randoms.java中出现过。这里演示filter(Predicate)操作:

【例子:filter(Predicate)的使用例】

import java.util.stream.LongStream;import static java.util.stream.LongStream.iterate;
import static java.util.stream.LongStream.rangeClosed;public class Prime {public static boolean isPrime(long n) {return rangeClosed(2, (long) Math.sqrt(n)) // rangeClosed()在这里是类似于循环的作用.noneMatch(i -> n % i == 0); // 若流为空,或流中没有元素能够与当前谓词匹配,返回true}public LongStream numbers() {return iterate(2, i -> i + 1).filter(Prime::isPrime); // 若返回结果是true,则保留下来}public static void main(String[] args) {new Prime().numbers().limit(10).forEach(n -> System.out.format("%d ", n));System.out.println();new Prime().numbers().skip(90).limit(10).forEach(n -> System.out.format("%d ", n));}
}

        程序执行的结果是:

        rangeClosed()的参数是一个左开右闭的区间,包含了上界值。若没有一个取余操作的结果是0,则noneMatch()返回true,否则返回false。并且noneMatch()会在第一次结果为false时退出。


将函数应用于每个流元素

        本条目用于介绍一些作用于每个流元素的各种map操作:

  • map(Function):将Function应用于输入流中的每个对象,结果作为输出流继续传递。

        以下是map面对不同类型的不同版本:

  • mapToInt(ToIntFunction):应用于IntStream中。
  • mapToLong(ToLongFunction):应用于LongStream中。
  • mapToDouble(ToDoubleFunction):应用于LongStream中。

【例子:将Function(通过map)映射到一个用String组成的流中】

import java.util.Arrays;
import java.util.function.Function;
import java.util.stream.Stream;public class FunctionMap {static String[] elements = {"12", "", "23", "45"};static Stream<String> testStream() {return Arrays.stream(elements);}static void test(String descr, Function<String, String> func) {System.out.println(" ---( " + descr + " )---");testStream().map(func).forEach(System.out::println);}public static void main(String[] args) {test("添加括号", s -> "[" + s + "]");test("数值增长", s -> {try {return Integer.parseInt(s) + 1 + ""; // parseInt()会尝试将String转换为Integer} catch (NumberFormatException e) { // 若无法完成转换,抛出异常,执行catch{}中的语句return s;}});test("替换", s -> s.replace("2", "9"));test("提取最后一位的数值",s -> s.length() > 0 ?s.charAt(s.length() - 1) + "" : s); }
}

        程序执行的结果是:

         在语句

return Integer.parseInt(s) + 1 + "";

中,表达式从左向右顺序进行,①先尝试将s转换为Integer,②再进行+1操作,③最后将其转换为字符串。

        另外,String.charAt()会返回指定索引处的char值。索引的范围是从0String.length()-1

---

        上述程序中,map()被用于将一个String映射到另一个String。而实际上,并没有约束要求生成的类型必须和输入的类型一致。因此还可以在map()中改变这个流的类型:

【例子:将基本类型的流映射到自定义类型中】

        在这个例子中,我们接受的是一个int类型的流,并且使用Numbered::new将其转换为了Numbered

---

        若Function生成的结果是某种数值类型,就需要使用相应的mapTo操作:

【例子:使用mapTo处理数值类型】

import java.util.stream.Stream;public class FunctionMap3 {public static void main(String[] args) {Stream.of("5", "7", "9").mapToInt(Integer::parseInt).forEach(n -> System.out.format("%d ", n));System.out.println();Stream.of("17", "19", "23").mapToLong(Long::parseLong).forEach(n -> System.out.format("%d ", n));System.out.println();Stream.of("17", "1.9", ".23").mapToDouble(Double::parseDouble).forEach(n -> System.out.format("%f ", n));}
}

        程序执行的结果是:


在应用map()期间组合流

        假设我们现在有得到了一个由传入元素组成的流,我们需要对其运用map()

我们希望得到的是一个String类型的流,但结果却是一个由指向其他流的“头”组成的流。换句话说,我们想要的是一个由元素组成的流,但却生成了一个与元素流组成的流

        这种时候就需要使用flatMap()。该方法会做两件事:

  1. 接受生成流的函数,并将其应用于传入元素(这一点和map()一样)。
  2. 然后,将每个流“扁平化”处理,将其展开为元素。

    和map()类似,flatMap()也有面对不同类型的不同版本(flatMapToInt()flatMapToLong()等)。

【例子:flatMap()的使用例】

import java.util.stream.Stream;public class FlatMap {public static void main(String[] args) {Stream.of(1, 2, 3).flatMap(i -> Stream.of("A", "B", "C")).forEach(System.out::println);}
}

        程序执行的结果是:

        从映射返回的每个流都被自动进行了扁平化处理,展开为组成这个流的String元素。

【例子:flatMapTo生成随机数】

import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;public class StreamOfRandoms {static Random rand = new Random(47);public static void main(String[] args) {Stream.of(1, 2, 3, 4, 5).flatMapToInt(i -> IntStream.concat( // concat()会按照参数的顺序将两个流组合到一起rand.ints(0, 100).limit(i), // 其中的每一个流的长度不超过iIntStream.of(-1))).forEach(n -> System.out.format("%d ", n));System.out.println();}
}

        程序执行的结果是:

        上述程序中出现了concat()

这个方法会按照参数的顺序将两个流组合到一起。所以,在每个有随机的Integer组成的流的末尾,都添加了一个-1作为标记。

    因为rand.ints()生成的是一个IntStream,所以这里使用的flatMap()concat()of()都是Integer的版本。

        在笔记12-1的FileToWordsRegexp.java中,我们将整个文件读取到内存的List中,这是需要存储空间的。但我们真正需要的,是一个不需要中间存储的单词流。这就是flatMap()解决的问题:

【例子:flatMap()创建占用少量内存的流】

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Pattern;
import java.util.stream.Stream;public class FileToWords {public static Stream<String> stream(String filepath)throws Exception {return Files.lines(Paths.get(filepath)).flatMap(line -> Pattern.compile("\\W+").splitAsStream(line));}
}

        stream()在这里是一个静态方法,因为它自己就可以完成整个流的创建。

        这里还出现了正则表达式\\W+\\W的意思是一个“非单词字符”,而+意味着“一个或是多个”。

    小写形式的\\w是指“单词字符”。

        由于语句

Pattern.compile().splitAsStream()

会生成一个流,所以若将其应用于map()操作中,我们会得到的是一个由单词流组成的流。而我们仅仅需要一个单词流而已。因此这里需要使用的是flatMap(),将其转化为一个由元素组成的简单流。

        除此之外,我们还可以使用String.split(),它会生成一个数组,这个数组可以经由Arrays.stream()转换为一个流:

.flatMap(line -> Arrays.stream(line.split("\\W+")))

此时得到的是一个真正的流(而不是像FileToWordsRegexp.java中那样,基于集合创建的流)。因此,每当我们想要一个新的流时,就必须从头创建,并且它无法复用

【例子:无法复用的流】

public class FileToWordsTest {public static void main(String[] args)throws Exception {FileToWords.stream("Cheese.dat").limit(7).forEach(s -> System.out.format("%s ", s));System.out.println();FileToWords.stream("Cheese.dat").skip(7).limit(2).forEach(s -> System.out.format("%s ", s));}
}

        程序执行的结果如下:

Optional类型

        在进行编程时,我们或许会认为流被连接成了一条“快乐通道”(指没有异常或错误情形发生的默认场景),并假设没有什么能够中断这个流。但事实是,只需要在流中放入一个null就可以破坏它。

    当从流中提取null时,对null进行的类型转换会发生异常。

        因此就需要Optional类型。这一类型实现了这样一个概念:存在一个对象,即可以作为流元素来占位,也可以在需要寻找的元素不存在时提醒我们(不会抛出异常)。

        某些标准的流操作会返回Optional对象,因为这些操作不能确保所要的结果一定存在:

  • findFirst():返回包含第一个元素的Optional
  • findAny():返回包含任何元素的Optional
  • max()min():返回包含流中最大值或最小值的Optional

        以上三种操作在流为空的时候都返回Optional.empty

  • reduce()的其中一个版本:这个版本不会把一个“identity”对象作为其第一个参数(其他版本中,“identity”是默认结果),

    它的返回值会被包在一个Optional中。
  • average():将数值化的流(IntStreamLongStreamDoubleStream)包在一个Optional中。

【例子:返回Optional类型的操作】

import java.util.stream.IntStream;
import java.util.stream.Stream;public class OptionalsFromEmptyStreams {public static void main(String[] args) {System.out.println(Stream.<String>empty().findFirst());System.out.println(Stream.<String>empty().findAny());System.out.println(Stream.<String>empty().max(String.CASE_INSENSITIVE_ORDER));System.out.println(Stream.<String>empty().min(String.CASE_INSENSITIVE_ORDER));System.out.println(Stream.<String>empty().reduce((s1, s2) -> s1 + s2));System.out.println(IntStream.empty().average());}
}

        程序执行的结果是:

        此时得到的结果不是抛出的异常,而是Optional.empty()对象。

        注意:这里通过Stream.<String>empty()创建了空流。若使用的是Stream.empty(),那么Java就无法通过这么有限的上下文信息推断出这个流的类型,但这种语法解决了这一问题:

Stream.<String> s = Stream.empty();

【例子:Optional的两个基本动作】

import java.util.Optional;
import java.util.stream.Stream;public class OptionalBasics {static void test(Optional<String> optString) {if (optString.isPresent()) // isPresent():若存在值,返回trueSystem.out.println(optString.get());elseSystem.out.println("流中不存在数据");}public static void main(String[] args) {test(Stream.of("一个元素").findFirst());test(Stream.<String>empty().findFirst());}
}

        程序执行的结果是:

        当接收了一个Optional时,首先调用了isPresent(),对流中元素的存在与否进行测试。

便捷函数

        有许多便捷函数,由于获取Optional中的数据。这些函数简化了上述例子的“先检查、再处理”的过程。

  • isPresent(Consumer):若值存在,则使用这个值调用Consumer。否则不进行任何动作。
  • orElse(otherObject):若对象存在,则返回这个对象。否则返回otherObject
  • orElseGet(Supplier):若对象存在,则返回这个对象。否则返回使用Supplier函数创建的替代对象。
  • orElseThrow(Supplier):若对象存在,则返回这个对象。否则抛出一个使用Supplier函数创建的异常。

【例子:便捷函数】

import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Stream;public class Optionals {static void basics(Optional<String> optString) {if (optString.isPresent())System.out.println(optString.get());elseSystem.out.println("流中不存在数据");}static void ifPresent(Optional<String> optString) {optString.ifPresent(System.out::println);}static void orElse(Optional<String> optString) {System.out.println(optString.orElse("从orElse()返回的对象"));}static void orElseGet(Optional<String> optString) {System.out.println(optString.orElseGet(() -> "orElseGet()替换的对象"));}static void orElseThrow(Optional<String> optString) {try {System.out.println(optString.orElseThrow(() -> new Exception("orElseThrow()替换的对象")));} catch (Exception e) { // 使用catch捕获Java库函数Optional::orElseThrow()抛出的异常System.out.println("捕获 " + e);}}static void test(String testName, Consumer<Optional<String>> cos) { // 一个可以接收所有示例方法的Consumer,避免代码重复System.out.println(" === " + testName + " === ");cos.accept(Stream.of("测试语句").findFirst());cos.accept(Stream.<String>empty().findFirst());}public static void main(String[] args) {test("basics", Optionals::basics);test("ifPresent", Optionals::ifPresent);test("orElse", Optionals::orElse);test("orElseGet", Optionals::orElseGet);test("orElseThrow", Optionals::orElseThrow);}
}

        程序执行的结果是:


创建Optional

        若要自己编写生成Optional的代码,可以使用以下三种静态方法:

  • empty():返回一个空的Optional
  • of(value):若已经确定这个value不是null,可以通过该方法将其包在一个Optional中。
  • ofNullable(value):若确定value是否为null,使用这个方法。若valuenull,该方法返回Optional.empty(),否则将这个value包在一个Optional中。

【例子:生成Optional的三个方法】

import java.util.Optional;public class CreatingOptionals {static void test(String testName, Optional<String> opt) {System.out.println(" === " + testName + " === ");System.out.println(opt.orElse("Null"));}public static void main(String[] args) {test("empty", Optional.empty());test("of", Optional.of("Value"));try {test("of", Optional.of(null));} catch (Exception e) {System.out.println(e);}test("ofNullable", Optional.ofNullable("Value"));test("ofNullable", Optional.ofNullable(null));}
}

        程序执行的结果如下:

        若试图通过of()传递null来创建Optional,就会抛出空指针异常。相比之下,ofNullable()显得更加安全。


Optional对象上的操作

        若生成了一个Optional,有三种方法可以在最后再做一项处理:

  • filter(Predicate):将Predicate应用于Optional的内容,并返回其结果。若OptionalPredicate不匹配,则返回empty。若Optionalempty,返回其本身。
  • map(Function):若Optional不是empty,将Function应用于Optional包含的对象,并返回结果。否则返回empty
  • flatMap(Function):与map()类似,但所提供的映射函数会将结果包在Optional中,这样flatMap()最后就不会再做任何包装了。

    但是,数值化的Optional上没有上述的这些操作。

        filter()方法存在于普通的流中和在Optional中。但它们的行为并不相同,在普通的流中,若Predicate返回falsefilter()会将元素从流中删除。而Optional中的filter()则会将其转换为empty

【例子:filter()的用法】

import java.util.Arrays;
import java.util.function.Predicate;
import java.util.stream.Stream;public class OptionalFilter {static String[] elements = {"Foo", "", "Bar", "Baz", "Bingo"};static Stream<String> testStream() {return Arrays.stream(elements);}static void test(String descr, Predicate<String> pred) {System.out.println(" ---( " + descr + " )---");for (int i = 0; i <= elements.length; i++) {System.out.println(testStream() // 注意:每次进入for循环,都会重新获取一个流.skip(i).findFirst().filter(pred));}}public static void main(String[] args) {test("true", str -> true);test("false", str -> false);test("str != \"\"", str -> str != "");test("str.length() == 3", str -> str.length() == 3);test("startsWith(\"B\")", str -> str.startsWith("B"));}
}

        程序执行的结果是:

        这次的程序虽然输出结果像一个流,但实际上每次进入for循环都会重新获取一个流。只是skip()操作会跳过元素,以至于结果看上去是一个流。

        这次for循环语句的结束条件并不是i < elements.length,而是i <= elements.length。因此最后一个元素事实上会超出这个流,但超出的部分自动变为了一个Optional.empty

        Optional也有自己的map()。不同的是,只有当Optional不为empty时,map()才会应用其的映射函数。

    若Optional不为空,则将其传递给函数时,map()会首先提取Optional中的对象。

【例子:Optional.map()的使用例】

import java.util.Arrays;
import java.util.function.Function;
import java.util.stream.Stream;public class OptionalMap {static String[] elements = {"12", "", "23", "45"};static Stream<String> testStream() {return Arrays.stream(elements);}static void test(String descr,Function<String, String> func) {System.out.println(" ---( " + descr + " )---");for (int i = 0; i <= elements.length; i++) {System.out.println(testStream().skip(i).findFirst() // 生成一个Optional.map(func));}}public static void main(String[] args) {test("加上括号", s -> "[" + s + "]");test("递增", s -> {try {return Integer.parseInt(s) + 1 + "";} catch (NumberFormatException e) {return s;}});test("替换", s -> s.replace("2", "9"));test("获取最后一位数字", s -> s.length() > 0 ?s.charAt(s.length() - 1) + "" : s);}
}

        程序执行的结果是:

        在函数完成之后,map()会先把结果包在一个Optional中,然后返回。并且,Optional.empty在遇到map()时直接通过,并没有被更改。

                OptionalflatMap()被应用于已经会生成Optional的映射函数,所以flatMap()并没有像map()一样进行包装的操作:

【例子:Optional.flatMap()的使用例】

import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;public class OptionalFlatMap {static String[] elements = {"12", "", "23", "45"};static Stream<String> testStream() {return Arrays.stream(elements);}static void test(String descr,Function<String, Optional<String>> func) { // Function的返回类型是Optional<String>System.out.println(" ---( " + descr + " )---");for (int i = 0; i <= elements.length; i++) {System.out.println(testStream().skip(i).findFirst().flatMap(func));}}public static void main(String[] args) {// 用Optional.of()将函数括起来test("加上括号", s -> Optional.of("[" + s + "]"));test("递增", s -> {try {return Optional.of(Integer.parseInt(s) + 1 + "");} catch (NumberFormatException e) {return Optional.of(s);}});test("替换", s -> Optional.of(s.replace("2", "9")));test("获取最后一位数字", s -> Optional.of(s.length() > 0 ?s.charAt(s.length() - 1) + "" : s));}
}

        程序执行的结果是:

        flatMap()map()唯一的区别在于,flatMap()不会将结果包在Optional中,这件事会交由映射函数来做。


由Optional组成的流

        Optional可以处理null值。所以若存在一个可能会生成null值的生成器,并且这个生成器创建了一个流,我们自然会想要将这些元素包含在Optional中。

【例子:由Optional组成的流】

import java.util.Optional;
import java.util.Random;
import java.util.stream.Stream;public class Signal {private final String msg;public Signal(String msg) {this.msg = msg;}public String getMsg() {return msg;}@Overridepublic String toString() {return "Signal(" + msg + ")";}static Random rand = new Random(47);public static Signal morse() {switch (rand.nextInt(4)) {case 1:return new Signal("dot");case 2:return new Signal("dash");default:return null;}}public static Stream<Optional<Signal>> stream() {return Stream.generate(Signal::morse).map(signal -> Optional.ofNullable(signal)); // 使用ofNullable将元素包入Optional中}
}

        当我们需要使用这个流的时候,我们需要考虑如何获取Optional中的对象:

【例子:从Optional的流中获取对象】

import java.util.Optional;public class StreamOfOptionals {public static void main(String[] args) {Signal.stream().limit(10).forEach(System.out::println);System.out.println(" ---");Signal.stream().limit(10).filter(Optional::isPresent).map(Optional::get).forEach(System.out::println);}
}

        程序执行的结果如下:

        从Optional的流中提取对象时,往往会遇到“没有值”的情况。这就需要我们针对不同的应用采取不同的方法。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Linux使用之xshell、xftp保姆教学(含安装包,详细使用方法,连接失败解决方法)

前言 链接: FTP&#xff0c;SSH服务器介绍 这是我之前写的一篇博客&#xff0c;其中介绍了Ubuntu操作系统的一些常用命令以及服务器介绍&#xff0c;这篇文章就向大家详细介绍如何安装及应用这些服务器&#xff0c;我以xshell、xftp为例。 安装包&#xff0c;使用方法&#xf…

华为云服务器内网vpc对等连接及微服务内网集群搭建处理

最近需要举办一场活动&#xff0c;某个业务访问量上升&#xff0c;有一定并发场景&#xff0c;为了活动能够顺利举行&#xff0c;解决方案就是将业务进行分布式&#xff0c;分布式部署到不同服务器&#xff0c;平摊用户请求&#xff0c;微服务使用的是SpringCloud Alibabanacos…

阿里云OSS图片存储

阿里云对象存储 OSS&#xff08;Object Storage Service&#xff09;是一款海量、安全、低成本、高可靠的云存储服务&#xff0c;提供最高可达 99.995 % 的服务可用性。多种存储类型供选择&#xff0c;全面优化存储成本。 视频介绍 创建bucket 开发文档 上传文件demo &#x…

树的存储结构以及树,二叉树,森林之间的转换

目录 1.双亲表示法 2.孩子链表 3.孩子兄弟表示法 4.树与二叉树的转换 &#xff08;1&#xff09;树转换为二叉树 &#xff08;2&#xff09;二叉树转换成树 5.二叉树与森林的转化 &#xff08;1&#xff09;森林转换为二叉树 以下树为例 1.双亲表示法 双亲表示法定义了…

Ai4science学习、教育和更多

11 学习、教育和更多 人工智能的进步为加速科学发现、推动创新和解决各个领域的复杂问题提供了巨大的希望。然而&#xff0c;要充分利用人工智能为科学研究带来的潜力&#xff0c;我们需要面对教育、人才培养和公众参与方面的新挑战。在本节中&#xff0c;我们首先收集了关于每…

Go-Ldap-Admin | openLDAP 同步钉钉、企业微信、飞书组织架构实践和部分小坑

目录 一、Docker-compose快速拉起demo测试环境 二、原生部署流程 安装MySQL&#xff1a;5.7数据库 安装openLDAP 修改域名&#xff0c;新增con.ldif 创建一个组织 安装OpenResty 下载后端 下载前端 部署后端 部署前端 三、管理动态字段 钉钉 企业微信 飞书 四、…

Unity自用工具:基于种子与地块概率的开放世界2D地图生成

public class BuildingGen : MonoBehaviour {public int[] Building;//存储要生成的地块代码public int[] Probability;//存储概率public double seed;public int width 100;public int height 100;public float noiseScale 0.1f; //噪声缩放倍数private int[,] frequencyM…

InnoDB索引机制

导学&#xff1a;索引什么时候失效&#xff1f;为什么类型转换索引会失效&#xff1f;不满足最左匹配原则&#xff1f; 我们都知道&#xff0c;MySQL它主要有2大模快组成&#xff0c;第一块就是我们的MySQL服务&#xff0c;里面包含了像连接管理、解析器、预处理、优化器、执行…

网络安全:个人信息保护,企业信息安全,国家网络安全的重要性

在当前的数字化时代&#xff0c;无论是个人&#xff0c;企业&#xff0c;还是国家&#xff0c;都会面临严重的网络安全威胁。网络安全不仅涉及我们的日常生活&#xff0c;也涉及到社会的稳定和国家的安全。这就需要我们高度重视网络安全&#xff0c;强化个人信息保护&#xff0…

【算法|动态规划No.7】leetcode300. 最长递增子序列

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

云原生微服务 第六章 Spring Cloud Netflix Eureka集成远程调用、负载均衡组件OpenFeign

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 文章目录 系列文章目录前言1、OpenFeign的实现…

Vue项目搭建图文详解教程

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 预备工作 请在本地创建文件夹用于存放Vue项目&#xff0c;例如&#xff1a;创建HelloWorld文件夹存放即将创建的Vue新项目。 创建Vue项目 首先&#xff0c;请在DOS中将目录…

【生命周期】

生命周期 1 引出生命周期2 分析生命周期3 总结生命周期 1 引出生命周期 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta …

windows WSL配置cuda,pytorch和jupyter notebook

机器配置 GPU: NVIDIA Quadro K2000 与 NVIDIA 驱动程序捆绑的CUDA版本 但按照维基百科的描述&#xff0c;我的GPU对应的compute capability3.0&#xff0c;允许安装的CUDA最高只支持10.2&#xff0c;如下所示。 为什么本地会显示11.4呢&#xff1f;对此&#xff0c;GPT是这…

【数据结构与算法】- 数组

数组 1.1 数组的定义1.2 数组的创建1.3 数组在内存中的情况2.1 初始化数组2.2 插入元素2.3 删除元素2.4 读取元素2.5 遍历数组 1.1 数组的定义 数组中的是在内存中是连续存储的&#xff0c;内存是由一个个内存单元组成的&#xff0c;每一个内存单元都有自己的地址&#xff0c;…

SpringBoot中使用Servlet和Filter

为什么要把Servlet和Filter写在一起,因为使用方式很相似 两种方式 第一种,使用Servlet和Filter 使用Servlet 继承HttpServlet 注册Servlet 使用Filter 1.自定义过滤器 2.注册过滤器 这里注意一点 使用/**无效 至少我这2.4.5版本是这样 过滤所有请求用/* 那么其实还有…

嵌入式Linux应用开发-驱动大全-第一章同步与互斥①

嵌入式Linux应用开发-驱动大全-第一章同步与互斥① 第一章 同步与互斥①1.1 内联汇编1.1.1 C语言实现加法1.1.2 使用汇编函数实现加法1.1.3 内联汇编语法1.1.4 编写内联汇编实现加法1.1.5 earlyclobber的例子 1.2 同步与互斥的失败例子1.2.1 失败例子11.2.2 失败例子21.2.3 失败…

高層建築設計和建造:從避難層到設備間和防風防火防水的設計理念,酒店住宅辦公樓都有什麽房間(精簡)

樓層概覽 標準層居住、辦公、商業等功能的樓層。結構和裝修與其他樓層相同&#xff0c;可供人正常居住、工作和活動避難層專門用於人員避難的樓層&#xff0c;通常會相隔數十個標準層&#xff0c;樓梯通常和標準層是錯開的(非公用)&#xff0c;具有更多的通風口。牆體和樓板具…

嵌入式Linux应用开发-驱动大全-第一章同步与互斥②

嵌入式Linux应用开发-驱动大全-第一章同步与互斥② 第一章 同步与互斥②1.3 原子操作的实现原理与使用1.3.1 原子变量的内核操作函数1.3.2 原子变量的内核实现1.3.2.1 ATOMIC_OP在 UP系统中的实现1.3.2.2 ATOMIC_OP在 SMP系统中的实现 1.3.3 原子变量使用案例1.3.4 原子位介绍1…

传输层协议——TCP、UDP

目录 1、UDP 协议&#xff08;用户数据报协议&#xff09; 协议特点 报文首部格式 2、TCP 协议&#xff08;传输控制协议&#xff09; 协议特点 报文首部格式 TCP连接建立时的三次握手 TCP拆除连接的四次挥手 TCP的流量控制 TCP的拥塞控制 3、传输层端口号 三类端口…