从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)

这篇具有很好参考价值的文章主要介绍了从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.不可变集合

1.1 什么是不可变集合

​ 是一个长度不可变,内容也无法修改的集合

1.2 使用场景

​ 如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。

​ 当集合对象被不可信的库调用时,不可变形式是安全的。

简单理解:

​ 不想让别人修改集合中的内容

比如说:

1,斗地主的54张牌,是不能添加,不能删除,不能修改的

2,斗地主的打牌规则:单张,对子,三张,顺子等,也是不能修改的

3,用代码获取的操作系统硬件信息,也是不能被修改的

1.3 不可变集合分类

  • 不可变的list集合
  • 不可变的set集合
  • 不可变的map集合

1.4 不可变的list集合

public class ImmutableDemo1 {
    public static void main(String[] args) {
        /*
            创建不可变的List集合
            "张三", "李四", "王五", "赵六"
        */

        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        List<String> list = List.of("张三", "李四", "王五", "赵六");

        System.out.println(list.get(0));
        System.out.println(list.get(1));
        System.out.println(list.get(2));
        System.out.println(list.get(3));

        System.out.println("---------------------------");

        for (String s : list) {
            System.out.println(s);
        }

        System.out.println("---------------------------");


        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }
        System.out.println("---------------------------");

        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }
        System.out.println("---------------------------");

        //list.remove("李四");
        //list.add("aaa");
        list.set(0,"aaa");
    }
}

1.5 不可变的Set集合

public class ImmutableDemo2 {
    public static void main(String[] args) {
        /*
           创建不可变的Set集合
           "张三", "李四", "王五", "赵六"


           细节:
                当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性
        */

        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        Set<String> set = Set.of("张三", "张三", "李四", "王五", "赵六");

        for (String s : set) {
            System.out.println(s);
        }

        System.out.println("-----------------------");

        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

        System.out.println("-----------------------");
        //set.remove("王五");
    }
}

1.6 不可变的Map集合

1.6.1:键值对个数小于等于10
public class ImmutableDemo3 {
    public static void main(String[] args) {
       /*
        创建Map的不可变集合
            细节1:
                键是不能重复的
            细节2:
                Map里面的of方法,参数是有上限的,最多只能传递20个参数,10个键值对
            细节3:
                如果我们要传递多个键值对对象,数量大于10个,在Map接口中还有一个方法
        */

        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        Map<String, String> map = Map.of("张三", "南京", "张三", "北京", "王五", "上海",
                "赵六", "广州", "孙七", "深圳", "周八", "杭州",
                "吴九", "宁波", "郑十", "苏州", "刘一", "无锡",
                "陈二", "嘉兴");

        Set<String> keys = map.keySet();
        for (String key : keys) {
            String value = map.get(key);
            System.out.println(key + "=" + value);
        }

        System.out.println("--------------------------");

        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "=" + value);
        }
        System.out.println("--------------------------");
    }
}
1.6.2:键值对个数大于10
public class ImmutableDemo4 {
    public static void main(String[] args) {

        /*
            创建Map的不可变集合,键值对的数量超过10个
        */

        //1.创建一个普通的Map集合
        HashMap<String, String> hm = new HashMap<>();
        hm.put("张三", "南京");
        hm.put("李四", "北京");
        hm.put("王五", "上海");
        hm.put("赵六", "北京");
        hm.put("孙七", "深圳");
        hm.put("周八", "杭州");
        hm.put("吴九", "宁波");
        hm.put("郑十", "苏州");
        hm.put("刘一", "无锡");
        hm.put("陈二", "嘉兴");
        hm.put("aaa", "111");

        //2.利用上面的数据来获取一个不可变的集合
/*
        //获取到所有的键值对对象(Entry对象)
        Set<Map.Entry<String, String>> entries = hm.entrySet();
        //把entries变成一个数组
        Map.Entry[] arr1 = new Map.Entry[0];
        //toArray方法在底层会比较集合的长度跟数组的长度两者的大小
        //如果集合的长度 > 数组的长度 :数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
        //如果集合的长度 <= 数组的长度:数据在数组中放的下,此时不会创建新的数组,而是直接用
        Map.Entry[] arr2 = entries.toArray(arr1);
        //不可变的map集合
        Map map = Map.ofEntries(arr2);
        map.put("bbb","222");*/


        //Map<Object, Object> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]));

        Map<String, String> map = Map.copyOf(hm);
        map.put("bbb","222");
    }
}

2.方法引用

2.1体验方法引用

  • 方法引用的出现原因

    在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作

    那么考虑一种情况:如果我们在Lambda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再写重复逻辑呢?答案肯定是没有必要

    那我们又是如何使用已经存在的方案的呢?

    这就是我们要讲解的方法引用,我们是通过方法引用来使用已经存在的方案

  • 代码演示

    public interface Printable {
        void printString(String s);
    }
    
    public class PrintableDemo {
        public static void main(String[] args) {
            //在主方法中调用usePrintable方法
    //        usePrintable((String s) -> {
    //            System.out.println(s);
    //        });
    	    //Lambda简化写法
            usePrintable(s -> System.out.println(s));
    
            //方法引用
            usePrintable(System.out::println);
    
        }
    
        private static void usePrintable(Printable p) {
            p.printString("爱生活爱Java");
        }
    }
    
    

2.2方法引用符

  • 方法引用符

    :: 该符号为引用运算符,而它所在的表达式被称为方法引用

  • 推导与省略

    • 如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导
    • 如果使用方法引用,也是同样可以根据上下文进行推导
    • 方法引用是Lambda的孪生兄弟

2.3引用类方法

​ 引用类方法,其实就是引用类的静态方法

  • 格式

    类名::静态方法

  • 范例

    Integer::parseInt

    Integer类的方法:public static int parseInt(String s) 将此String转换为int类型数据

  • 练习描述

    • 定义一个接口(Converter),里面定义一个抽象方法 int convert(String s);
    • 定义一个测试类(ConverterDemo),在测试类中提供两个方法
      • 一个方法是:useConverter(Converter c)
      • 一个方法是主方法,在主方法中调用useConverter方法
  • 代码演示

    public interface Converter {
        int convert(String s);
    }
    
    public class ConverterDemo {
        public static void main(String[] args) {
    
    		//Lambda写法
            useConverter(s -> Integer.parseInt(s));
    
            //引用类方法
            useConverter(Integer::parseInt);
    
        }
    
        private static void useConverter(Converter c) {
            int number = c.convert("666");
            System.out.println(number);
        }
    }
    
  • 使用说明

    Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数

2.4引用对象的实例方法

​ 引用对象的实例方法,其实就引用类中的成员方法

  • 格式

    对象::成员方法

  • 范例

    “HelloWorld”::toUpperCase

    String类中的方法:public String toUpperCase() 将此String所有字符转换为大写

  • 练习描述

    • 定义一个类(PrintString),里面定义一个方法

      public void printUpper(String s):把字符串参数变成大写的数据,然后在控制台输出

    • 定义一个接口(Printer),里面定义一个抽象方法

      void printUpperCase(String s)

    • 定义一个测试类(PrinterDemo),在测试类中提供两个方法

      • 一个方法是:usePrinter(Printer p)
      • 一个方法是主方法,在主方法中调用usePrinter方法
  • 代码演示

    public class PrintString {
        //把字符串参数变成大写的数据,然后在控制台输出
        public void printUpper(String s) {
            String result = s.toUpperCase();
            System.out.println(result);
        }
    }
    
    public interface Printer {
        void printUpperCase(String s);
    }
    
    public class PrinterDemo {
        public static void main(String[] args) {
    
    		//Lambda简化写法
            usePrinter(s -> System.out.println(s.toUpperCase()));
    
            //引用对象的实例方法
            PrintString ps = new PrintString();
            usePrinter(ps::printUpper);
    
        }
    
        private static void usePrinter(Printer p) {
            p.printUpperCase("HelloWorld");
        }
    }
    
    
  • 使用说明

    Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数

2.5引用类的实例方法

​ 引用类的实例方法,其实就是引用类中的成员方法

  • 格式

    类名::成员方法

  • 范例

    String::substring

    public String substring(int beginIndex,int endIndex)

    从beginIndex开始到endIndex结束,截取字符串。返回一个子串,子串的长度为endIndex-beginIndex

  • 练习描述

    • 定义一个接口(MyString),里面定义一个抽象方法:

      String mySubString(String s,int x,int y);

    • 定义一个测试类(MyStringDemo),在测试类中提供两个方法

      • 一个方法是:useMyString(MyString my)
      • 一个方法是主方法,在主方法中调用useMyString方法
  • 代码演示

    public interface MyString {
        String mySubString(String s,int x,int y);
    }
    
    public class MyStringDemo {
        public static void main(String[] args) {
    		//Lambda简化写法
            useMyString((s,x,y) -> s.substring(x,y));
    
            //引用类的实例方法
            useMyString(String::substring);
    
        }
    
        private static void useMyString(MyString my) {
            String s = my.mySubString("HelloWorld", 2, 5);
            System.out.println(s);
        }
    }
    
  • 使用说明

    ​ Lambda表达式被类的实例方法替代的时候
    ​ 第一个参数作为调用者
    ​ 后面的参数全部传递给该方法作为参数

2.6引用构造器

​ 引用构造器,其实就是引用构造方法

  • l格式

    类名::new

  • 范例

    Student::new

  • 练习描述

    • 定义一个类(Student),里面有两个成员变量(name,age)

      并提供无参构造方法和带参构造方法,以及成员变量对应的get和set方法

    • 定义一个接口(StudentBuilder),里面定义一个抽象方法

      Student build(String name,int age);

    • 定义一个测试类(StudentDemo),在测试类中提供两个方法

      • 一个方法是:useStudentBuilder(StudentBuilder s)
      • 一个方法是主方法,在主方法中调用useStudentBuilder方法
  • 代码演示

    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        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 interface StudentBuilder {
        Student build(String name,int age);
    }
    
    public class StudentDemo {
        public static void main(String[] args) {
    
    		//Lambda简化写法
            useStudentBuilder((name,age) -> new Student(name,age));
    
            //引用构造器
            useStudentBuilder(Student::new);
    
        }
    
        private static void useStudentBuilder(StudentBuilder sb) {
            Student s = sb.build("林青霞", 30);
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
    
  • 使用说明

    Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数

后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹
文章来源地址https://www.toymoban.com/news/detail-723889.html

到了这里,关于从零开始学习 Java:简单易懂的入门指南之不可变集合、方法引用(二十六)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零开始学习 Java:简单易懂的入门指南之多态(十)

    多态是继封装、继承之后,面向对象的第三大特性。 多态是出现在继承或者实现关系中的 。 多态体现的格式 : 多态的前提 :有继承关系,子类对象是可以赋值给父类类型的变量。例如Animal是一个动物类型,而Cat是一个猫类型。Cat继承了Animal,Cat对象也是Animal类型,自然可

    2024年02月12日
    浏览(67)
  • 从零开始学习 Java:简单易懂的入门指南之爬虫(十六)

    Pattern:表示正则表达式 Matcher:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。 在大串中去找符合匹配规则的子串。 代码示例: 需求: ​ 把连接:https://m.sengzan.com/jiaoyu/29104.html?ivk sa=1025883i中所有的身份证号码都爬取出来。 代码示例: 需求: ​ 把

    2024年02月11日
    浏览(72)
  • 从零开始学习 Java:简单易懂的入门指南之类和对象(七)

    1.1 类和对象的理解 客观存在的事物皆为对象 ,所以我们也常常说万物皆对象。 类 类的理解 类是对现实生活中一类具有共同属性和行为的事物的抽象 类是对象的数据类型,类是具有相同属性和行为的一组对象的集合 简单理解:类就是对现实事物的一种描述 类的组成 属性:

    2024年02月14日
    浏览(72)
  • 从零开始学习 Java:简单易懂的入门指南之面向对象(九)

    类的定义格式如下: 例如: 例如: 1.3.1 封装的步骤 1.使用 private 来修饰成员变量。 2.使用 public 修饰getter和setter方法。 1.3.2 封装的步骤实现 private修饰成员变量 public修饰getter和setter方法 1.4.1 构造方法的作用 在创建对象的时候,给成员变量进行初始化。 初始化即赋值的意

    2024年02月13日
    浏览(82)
  • 从零开始学习 Java:简单易懂的入门指南之异常(二十八)

    异常,就是不正常的意思。在生活中:医生说,你的身体某个部位有异常,该部位和正常相比有点不同,该部位的功能将受影响.在程序中的意思就是: 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。 在Java等面向对象的编程语言中,异常本身

    2024年02月08日
    浏览(75)
  • 从零开始学习 Java:简单易懂的入门指南之反射(三十八)

    ​ 专业的解释: ​ 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; ​ 对于任意一个对象,都能够调用它的任意属性和方法; ​ 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。 ​ 通俗的理解: 利用 反射 创建的对象 可

    2024年02月08日
    浏览(49)
  • 从零开始学习 Java:简单易懂的入门指南之包装类(十九)

    Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类,如下: 基本类型 对应的包装类(位于java.lang包中) byte

    2024年02月11日
    浏览(54)
  • 从零开始学习 Java:简单易懂的入门指南之时间类(十七)

    java.util.Date`类 表示特定的瞬间,精确到毫秒。 继续查阅Date类的描述,发现Date拥有多个构造函数,只是部分已经过时,我们重点看以下两个构造函数 public Date() :从运行程序的此时此刻到时间原点经历的毫秒值,转换成Date对象,分配Date对象并初始化此对象,以表示分配它的时

    2024年02月11日
    浏览(197)
  • 从零开始学习 Java:简单易懂的入门指南之线程池(三十六)

    当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程 状态被定义在了java.lang.Thread.State枚举类中,State枚举类的源码如下: 通过源码我们可以看到Ja

    2024年02月08日
    浏览(52)
  • 从零开始学习 Java:简单易懂的入门指南之线程同步(三十五)

    1.1卖票【应用】 案例需求 某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票 实现步骤 定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:private int tickets = 100; 在SellTicket类中重写run()方法实现卖票,代码步骤如下

    2024年02月08日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包