【愚公系列】2023年10月 Java教学课程 051

编程入门 行业动态 更新时间:2024-10-25 06:32:40

【<a href=https://www.elefans.com/category/jswz/34/1769546.html style=愚公系列】2023年10月 Java教学课程 051"/>

【愚公系列】2023年10月 Java教学课程 051

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

文章目录

  • 🚀一、可变参数
    • 🔎1.概念
    • 🔎2.作用
    • 🔎3.案例
    • 🔎4.注意事项
  • 🚀二、不可变集合
    • 🔎1.概念
    • 🔎2.作用
    • 🔎3.案例
    • 🔎4.注意事项
  • 🚀三、Stream流
    • 🔎1.Stream流的概述
    • 🔎2.Stream流的获取
    • 🔎3.Stream流的常用API
    • 🔎4.Stream流的收集操作
    • 🔎5.Stream流综合练习
  • 🚀感谢:给读者的一封信


🚀一、可变参数

🔎1.概念

Java中可变参数是一种特殊的参数类型,允许方法在调用时使用不同数量的参数。使用可变参数可以使方法更加灵活,可以接受任意数量的参数。

可变参数由三个点(…)表示,它必须是方法的最后一个参数。在方法体内,可以将可变参数看作是数组形式的参数,因此可以使用数组的相关方法和语法来处理可变参数。

例如,下面是一个使用可变参数的方法的示例:

public static int sum(int... nums) {int result = 0;for (int n : nums) {result += n;}return result;
}

在调用该方法时,可以传入任意数量的参数:

int result1 = sum(1, 2, 3); // result1 = 6
int result2 = sum(1, 2, 3, 4, 5); // result2 = 15
int result3 = sum(); // result3 = 0

注意,在实际应用中,可变参数应该谨慎使用,以避免出现意外的行为。同时,使用可变参数也会对性能产生一定影响。

🔎2.作用

Java中的可变参数可以方便地将不定数量的参数传递给一个方法。这样,不需要在方法定义时确定参数的数量,从而提高了方法的灵活性和可重用性。可变参数的语法是在参数类型后面加上三个点(…),表示可以接受任意数量的参数。在方法内部,可变参数被当作一个数组来处理,可以通过循环遍历来处理每一个参数。同时,Java也提供了一些内置方法来操作可变参数,例如Arrays.asList()方法可以将一个序列转换成一个List对象。

🔎3.案例

下面是一个使用可变参数的例子,实现了一个方法来打印多个字符串:

public class VarargsExample {public static void main(String[] args) {printStrings("Hello", "World"); // 输出 "Hello World"printStrings("Java", "is", "fun"); // 输出 "Java is fun"}public static void printStrings(String... strings) {for (String s : strings) {System.out.print(s + " ");}System.out.println();}
}

在上面的代码中,我们定义了一个名为printStrings的方法,参数列表中使用了可变参数String... strings,表示可以接收任意数量的字符串参数。

在方法体内部,我们使用了一个for循环来遍历这个可变参数strings,并将每个字符串都输出到控制台上。最后,在每个字符串后面加上一个空格,最后输出一个换行符,以便下一个输出语句不会与前一个输出语句在同一行上。

🔎4.注意事项

  1. 可变参数必须是方法的最后一个参数。
  2. 可变参数只能有一个,不能出现多个。
  3. 可变参数的类型必须是数组类型,且元素类型必须确定。
  4. 可变参数可以不传递参数,此时会创建一个长度为0的数组。
  5. 如果同时有多个参数,可变参数的前面的参数类型和数量必须确定,后面的可变参数必须放在最后。
  6. 传递参数时可以使用数组,也可以使用逗号分隔的参数列表格式。
  7. 可变参数的类型不能是基本类型,只能是引用类型。

🚀二、不可变集合

🔎1.概念

Java中的不可变集合是指创建后不能被修改的集合。一旦创建了不可变集合,不能添加、删除或修改其中的元素,只能读取其中的元素。Java提供了许多不可变集合类,例如:

  1. 不可变列表:java.util.Collections.unmodifiableList()
  2. 不可变集合:java.util.Collections.unmodifiableSet()
  3. 不可变映射:java.util.Collections.unmodifiableMap()

使用不可变集合的好处是:

  1. 线程安全:不可变集合在多线程环境下是安全的,因为它们没有被修改的风险。
  2. 性能优化:由于不可变集合是不可修改的,它们可以被缓存、重复使用,从而提高性能。
  3. 代码安全性:由于不可变集合不能被修改,它们可以减少由于意外修改导致的代码错误。

值得注意的是,虽然不可变集合不能被修改,但是它们可以被替换为新的集合。例如,可以使用新的集合替换已经存在的不可变集合。这种方式可以让代码更加灵活,同时保持不可变集合的优点。

🔎2.作用

不可变集合在Java中的作用是保证数据的不可修改性,从而提高代码的安全性和可维护性。使用不可变集合可以避免在多线程环境中出现的并发问题。

Java中提供了多种不可变集合类,如不可变列表类ImmutableList、不可变集合类ImmutableSet、不可变映射类ImmutableMap等,这些类都是通过复制原始集合并在内部进行不可修改操作来实现的。

使用不可变集合的好处是:

  1. 安全性:不可变集合可以防止数据被其他代码修改,从而避免数据泄漏和安全漏洞。

  2. 可维护性:不可变集合可以减少代码维护难度,更容易理解和调试。

  3. 性能:尽管使用不可变集合类需要创建新的对象,但是由于不需要进行修改操作,因此可以获得更好的性能。此外,由于不可变集合不需要进行线程同步操作,因此在多线程环境中可以获得更好的性能。

对于需要保证安全性和可维护性的Java应用程序,使用不可变集合是一个很好的选择。

🔎3.案例

Java中提供了不可变集合类,可以使用它们创建不可变集合对象。不可变集合是指一旦创建就不能被修改的集合,任何尝试修改不可变集合的操作都将返回一个新的不可变集合对象。以下是Java中不可变集合的示例:

  1. 不可变List:
import java.util.Collections;
import java.util.List;public class ImmutableCollectionsExample {public static void main(String[] args) {List<String> immutableList = Collections.unmodifiableList(Arrays.asList("apple", "banana", "orange"));System.out.println(immutableList);// immutableList.add("grape"); // This will throw an UnsupportedOperationException}
}

在上述代码中,我们使用Collections.unmodifiableList()方法创建了一个不可变List,如果尝试修改该List,将抛出UnsupportedOperationException异常。

  1. 不可变Set:
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;public class ImmutableCollectionsExample {public static void main(String[] args) {Set<String> immutableSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("red", "green", "blue")));System.out.println(immutableSet);// immutableSet.add("yellow"); // This will throw an UnsupportedOperationException}
}

在上述代码中,我们使用Collections.unmodifiableSet()方法创建了一个不可变Set,如果尝试修改该Set,将抛出UnsupportedOperationException异常。

  1. 不可变Map:
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;public class ImmutableCollectionsExample {public static void main(String[] args) {Map<String, Integer> immutableMap = Collections.unmodifiableMap(new HashMap<String, Integer>() {{put("apple", 1);put("banana", 2);put("orange", 3);}});System.out.println(immutableMap);// immutableMap.put("grape", 4); // This will throw an UnsupportedOperationException}
}

在上述代码中,我们使用Collections.unmodifiableMap()方法创建了一个不可变Map,如果尝试修改该Map,将抛出UnsupportedOperationException异常。

通过使用不可变集合,我们可以确保集合内容的安全性,并避免不小心改变其内容的错误。

🔎4.注意事项

Java中不可变集合是指一旦创建就不能修改的集合。它们是线程安全的,因为多个线程可以同时访问它们而不会导致数据损坏或不一致。以下是使用不可变集合时应注意的事项:

  1. 不可变集合的创建是一个开销较大的操作,因为每次修改集合时都需要创建一个新的集合对象。因此,应尽量避免在性能敏感的代码中频繁地创建不可变集合。

  2. 不可变集合不支持修改操作,因此在需要修改集合的情况下,需要使用可变集合来完成。但是,可以通过创建新的不可变集合来模拟修改操作。例如,通过使用不可变集合的“add”方法创建一个新集合来模拟添加元素的操作。

  3. 在使用不可变集合时,应注意避免在迭代或循环操作中修改集合。这可能会导致ConcurrentModificationException异常。

  4. 当使用不可变集合时,需要将其视为只读集合。尝试修改不可变集合将导致UnsupportedOperationException异常。

  5. 不可变集合可以通过Collections.unmodifiableXXX方法创建。这些方法将返回一个只读的不可变集合,而不是一个真正的不可变集合。因此,如果持有一个只读的不可变集合,应将其视为只读集合,并避免在其上执行修改操作。

  6. 不要将可变集合转换为不可变集合,因为这不是线程安全的。如果需要创建不可变集合,请使用正确的方法来创建它们。

List、Set、Map接口中,都存在of方法可以创建不可变集合,相关案例如下:

public static void main(String[] args) {// 1、不可变的List集合List<Double> lists = List.of(569.5, 700.5, 523.0,  570.5);// lists.add(99.9);System.out.println(lists.get(2));// 2、不可变的Set集合Set<String> names = Set.of("迪丽热巴", "迪丽热九", "马尔扎哈", "卡尔眨巴" );// names.add("迪丽热九");System.out.println(names);// 3、不可变的Map集合Map<String, Integer> maps = Map.of("huawei",2, "Java开发", 1 , "手表", 1);maps.put("huawei",100);System.out.println(maps);
}

🚀三、Stream流

🔎1.Stream流的概述

Java中的Stream流是一个用于处理集合数据的API,它提供了一种更加简单和直接的方式来操作集合数据。Stream流在Java 8中首次引入,它可以处理一些常见的集合操作,例如筛选、映射、聚合等。

Stream流可以分为两种类型:中间操作和终端操作。中间操作只是对数据进行转换和过滤,例如map()、filter()、distinct()等。而终端操作则是对流的数据进行计算、汇总或输出,例如count()、reduce()、forEach()等。

使用Stream流可以简化代码,提高效率和可读性,下面是Stream流的基本使用:

  1. 创建Stream流:可以通过集合、数组、IO等方式来创建Stream流;
  2. 中间操作:使用中间操作对数据进行过滤、转换等操作;
  3. 终端操作:使用终端操作对数据进行计算、汇总或输出。

例如,对于一个List集合,如果想要筛选出其中所有年龄大于18的人的名字,可以使用以下代码:

List<Person> list = new ArrayList<>();
//添加数据List<String> names = list.stream().filter(p -> p.getAge() > 18).map(Person::getName).collect(Collectors.toList());

上述代码中,首先将List集合转换为Stream流,然后使用filter()方法筛选出年龄大于18的人,接着使用map()方法将符合条件的人的名字提取出来,最后使用collect()方法将名字转换为一个List集合。

🔎2.Stream流的获取


在Java中,Stream流可以通过以下方式获取:

  1. 从集合获取流:可以通过集合的stream()方法,将集合转换为流。例如:
List<String> list = Arrays.asList("apple", "banana", "orange");
Stream<String> stream = list.stream();
  1. 从数组获取流:可以通过Arrays类的stream()方法,将数组转换为流。例如:
int[] arr = new int[]{1, 2, 3, 4, 5};
IntStream stream = Arrays.stream(arr);
  1. 通过Stream.of()方法获取流:可以通过Stream类的of()方法,直接获取一个流。例如:
Stream<String> stream = Stream.of("apple", "banana", "orange");
  1. 通过文件获取流:可以通过Java NIO中的Files.lines()方法,从文件中获取流。例如:
Path path = Paths.get("file.txt");
Stream<String> stream = Files.lines(path);
  1. 通过生成器获取流:可以通过Stream.generate()方法,通过自定义函数生成一个流。例如:
Stream<Integer> stream = Stream.generate(() -> 1);
  1. 通过迭代器获取流:可以通过Stream.iterate()方法,通过迭代器生成一个流。例如:
Stream<Integer> stream = Stream.iterate(1, n -> n + 1);

案例如下:

public static void main(String[] args) {/** --------------------获取Collection系列集合的Stream流-------------------------------   */Collection<String> list = new ArrayList<>();Stream<String> s1 = list.stream();/** --------------------获取Map系列集合的Stream流-------------------------------   */Map<String, Integer> maps = new HashMap<>();// 键流Stream<String> s2 = maps.keySet().stream();// 值流Stream<Integer> s3 = maps.values().stream();// 键值对流(拿整体)Stream<Map.Entry<String, Integer>> stream = maps.entrySet().stream();/** ---------------------获取数组的Stream流------------------------------   */String[] names = {"赵敏","小昭","灭绝","周芷若"};// 两种写法的效果是一样的!Stream<String> s4 = Arrays.stream(names);Stream<String> s5 = Stream.of(names);
}

🔎3.Stream流的常用API

API名称作用示例
filter()过滤流中的元素List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
map()对流中的元素进行转换List<String> words = Arrays.asList("hello", "world");List<Integer> wordLengths = words.stream().map(String::length).collect(Collectors.toList());
flatMap()对流中的每个元素进行转换,并将结果合并为一个流List<List<String>> namesNested = Arrays.asList( Arrays.asList("Jeff", "Bezos"), Arrays.asList("Bill", "Gates"), Arrays.asList("Mark", "Zuckerberg"));List<String> namesFlatStream = namesNested.stream().flatMap(Collection::stream).collect(Collectors.toList());
distinct()去除流中重复的元素List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 2, 4, 1);List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());
sorted()对流中的元素进行排序List<Integer> numbers = Arrays.asList(3, 2, 1, 4, 5);List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList());
peek()对流中的每个元素执行特定的操作,通常用于调试List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).peek(System.out::println).collect(Collectors.toList());
limit()限制流中的元素数量List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> firstTwoNumbers = numbers.stream().limit(2).collect(Collectors.toList());
skip()跳过流中的前若干个元素List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> lastThreeNumbers = numbers.stream().skip(2).collect(Collectors.toList());
forEach()对流中的每个元素执行特定的操作List<String> names = Arrays.asList("Alice", "Bob", "Charlie");names.stream().forEach(System.out::println);
reduce()对流中的元素进行归约操作,返回一个值List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);int sum = numbers.stream().reduce(0, Integer::sum);

示例代码与注释:

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;public class StreamDemo {public static void main(String[] args) {// 创建一个List对象List<String> words = Arrays.asList("hello", "world", "java", "stream");// 使用filter和collect方法过滤出长度大于4的单词List<String> filteredWords = words.stream().filter(word -> word.length() > 4).collect(Collectors.toList());System.out.println(filteredWords); // [world, stream]// 使用map和collect方法将单词转换为大写形式List<String> uppercaseWords = words.stream().map(String::toUpperCase).collect(Collectors.toList());System.out.println(uppercaseWords); // [HELLO, WORLD, JAVA, STREAM]// 使用flatMap和collect方法将多个List合并为一个List,并去重List<List<String>> nestedLists = Arrays.asList(Arrays.asList("hello", "world"),Arrays.asList("java", "stream"),Arrays.asList("hello", "java"));List<String> uniqueWords = nestedLists.stream().flatMap(Collection::stream).distinct().collect(Collectors.toList());System.out.println(uniqueWords); // [hello, world, java, stream]// 使用sorted方法对List进行排序List<Integer> numbers = Arrays.asList(5, 2, 3, 1, 4);List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList());System.out.println(sortedNumbers); // [1, 2, 3, 4, 5]// 使用peek方法输出每个元素的值List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).peek(System.out::println).collect(Collectors.toList());// 输出为:// 2// 4System.out.println(evenNumbers); // [2, 4]// 使用limit方法限制输出元素的数量List<Integer> firstThreeNumbers = numbers.stream().limit(3).collect(Collectors.toList());System.out.println(firstThreeNumbers); // [5, 2, 3]// 使用skip方法跳过前两个元素List<Integer> lastThreeNumbers = numbers.stream().skip(2).collect(Collectors.toList());System.out.println(lastThreeNumbers); // [3, 1, 4]// 使用forEach方法输出每个元素的值words.stream().forEach(System.out::println);// 输出为:// hello// world// java// stream// 使用reduce方法求List中所有元素的和int sum = numbers.stream().reduce(0, Integer::sum);System.out.println(sum); // 15}
}

🔎4.Stream流的收集操作

以下是Java中Stream流的常用收集操作及示例:

操作方法示例
转化为Listcollect(Collectors.toList())List<String> list = Stream.of(“a”, “b”, “c”).collect(Collectors.toList());
转化为Setcollect(Collectors.toSet())Set<String> set = Stream.of(“a”, “b”, “c”).collect(Collectors.toSet());
转化为Mapcollect(Collectors.toMap(key, value))Map<String, Integer> map = Stream.of(“a”, “aa”, “aaa”).collect(Collectors.toMap(Function.identity(), String::length));
转化为GroupingMapcollect(Collectors.groupingBy(key))Map<Integer, List<String>> map = Stream.of(“a”, “b”, “aa”, “bb”, “aaa”, “bbb”).collect(Collectors.groupingBy(String::length));
转化为统计结果collect(Collectors.summarizingInt/Long/Double)IntSummaryStatics stats = Stream.of(1, 2, 3, 4, 5).collect(Collectors.summarizingInt(Integer::intValue));

PS:其中 key 代表作为Map的key的函数, value 代表作为Map的value的函数,可以是Lambda表达式或方法引用, Function.identity() 代表不改变元素的函数。

示例代码:

import java.util.*;
import java.util.stream.Collectors;public class StreamCollect {public static void main(String[] args) {// 转化为ListList<String> list = Stream.of("a", "b", "c").collect(Collectors.toList());System.out.println(list);   // [a, b, c]// 转化为SetSet<String> set = Stream.of("a", "b", "c").collect(Collectors.toSet());System.out.println(set);   // [a, b, c]// 转化为MapMap<String, Integer> map = Stream.of("a", "aa", "aaa").collect(Collectors.toMap(s -> s, String::length));System.out.println(map);   // {a=1, aa=2, aaa=3}// 转化为GroupingMapMap<Integer, List<String>> groupingMap = Stream.of("a", "b", "aa", "bb", "aaa", "bbb").collect(Collectors.groupingBy(String::length));System.out.println(groupingMap);   // {1=[a, b], 2=[aa, bb], 3=[aaa, bbb]}// 转化为统计结果IntSummaryStatistics stats = Stream.of(1, 2, 3, 4, 5).collect(Collectors.summarizingInt(Integer::intValue));System.out.println(stats);   // IntSummaryStatistics{count=5, sum=15, min=1, average=3.000000, max=5}}
}

🔎5.Stream流综合练习

假设有一个Person类,包含姓名、年龄、性别三个属性:

public class Person {private String name;private int age;private String gender;public Person(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", gender='" + gender + '\'' +'}';}
}

现在需要对一个Person列表进行以下操作:

  1. 找出所有年龄大于18岁的人,按照年龄降序排列,只输出姓名和年龄
  2. 找出所有女性的平均年龄
  3. 找出所有男性的最小年龄
  4. 统计每个性别的人数

完整的代码如下:

import java.util.*;
import java.util.stream.Collectors;public class StreamDemo {public static void main(String[] args) {List<Person> personList = new ArrayList<>();personList.add(new Person("张三", 23, "男"));personList.add(new Person("李四", 21, "男"));personList.add(new Person("王五", 19, "女"));personList.add(new Person("赵六", 25, "女"));personList.add(new Person("钱七", 17, "男"));personList.add(new Person("孙八", 30, "女"));// 找出所有年龄大于18岁的人,按照年龄降序排列,只输出姓名和年龄List<String> nameAndAge = personList.stream().filter(person -> person.getAge() > 18).sorted((p1, p2) -> p2.getAge() - p1.getAge()).map(person -> person.getName() + ":" + person.getAge()).collect(Collectors.toList());System.out.println("nameAndAge = " + nameAndAge);// 找出所有女性的平均年龄OptionalDouble femaleAverageAge = personList.stream().filter(person -> person.getGender().equals("女")).mapToInt(Person::getAge).average();if (femaleAverageAge.isPresent()) {System.out.println("femaleAverageAge = " + femaleAverageAge.getAsDouble());} else {System.out.println("没有女性");}// 找出所有男性的最小年龄OptionalInt maleMinAge = personList.stream().filter(person -> person.getGender().equals("男")).mapToInt(Person::getAge).min();if (maleMinAge.isPresent()) {System.out.println("maleMinAge = " + maleMinAge.getAsInt());} else {System.out.println("没有男性");}// 统计每个性别的人数Map<String, Long> genderCount = personList.stream().collect(Collectors.groupingBy(Person::getGender, Collectors.counting()));System.out.println("genderCount = " + genderCount);}
}

🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

更多推荐

【愚公系列】2023年10月 Java教学课程 051

本文发布于:2024-02-12 03:59:46,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1685812.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:愚公   课程   系列   Java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!