Java学习第二周总结

3 阅读6分钟

最开始还准备一周一总结,结果因为懒鸽了这么多周,这周就从第二周开始算。

先说下都学了什么,从泛型Map/Set 集合用法,到Lambda 表达式、方法引用,我觉得这部分好抽象,学的时候也很吃力,所以遇到了相当多的问题,也可能是我没有去用的原因。本篇总结将对我遇到的问题,我不理解的地方做个总结。

一、泛型:保障数据类型不会出错,简化代码

先学的是泛型,从 “为什么要用”“什么时候用”两个问题,我理解了泛型。

1. 为什么要用

(1)有一些限定集合 / 工具类的存储类型,你去存数据的时候,可能会手误把另一种数据存进去了,这时候明显是有问题的。但它在编译时不显示错误,在运行时给你报一个ClassCastException异常 (2)这种存储类型,不管你存进去是什么类型,取出来都是Object,所以取出来还要强转

// 不使用泛型:需要强制转换,麻烦且不安全 
List list = new ArrayList(); 
list.add("Java"); 
//这个编译不报错,但运行时报错
//list.add(100);
String s1 = (String) list.get(0); // 必须强转 

// 使用泛型:不用强转,安全、简洁、清晰 
List<String> list2 = new ArrayList<>(); list2.add("Java"); S
tring s2 = list2.get(0); // 直接使用,无需强转

为了解决这些问题,泛型诞生了。把类型名填入<>,对类型强制规范,让错误在编译时给你报出来,避免运行时异常
让你存进去什么类型,取出来还是什么类型,免去强制类型转换

2. 关键疑问解答

不强转会怎样:不用泛型时,集合存储的都是Object类型,无法调用子类特有方法,必须强转才能使用;

足够细心能不能不用泛型?这是我的一个疑问。答案是可以,但人无法保证永远不出错,泛型能把错误提前到编译期,项目更稳健;

3. 使用场景判断

必须用:通用容器、工具类、需要保证类型安全的场景,如List、Set、Map;
不用:仅处理单一固定类型、无需复用的简单业务逻辑。

二、Map 集合:遍历、Entry 与 TreeMap 排序

Map 是本周学习的一个难点集合,理清了HashMap遍历规则、Entry作用,以及TreeMap使用注意事项。

1. 先说Map是什么,为什么用,什么时候用

  • Map 是一种用来存储「键值对(Key-Value)」的集合,就像字典一样,根据Key能找到Value
  • 根据 key 快速查找 value,速度极快;需要一个集合能存储一对一对的数据
  • 存在一一对应关系数据,用map存储;需要快速查找;需要做映射

2. HashMap 三大遍历方法

  • keySet():获取所有键的Set集合(键唯一,匹配Set不可重复特性);
  • values():获取所有值的Collection集合(值可重复,用Collection更适配);
  • entrySet()最推荐遍历方式,获取Entry键值对集合,一次性拿到 key 和 value,高效无冗余。

3. Map.Entry 的作用

Entry是 Map 中键值对的封装对象entrySet()将所有 key+value 打包成集合,遍历时直接获取对应关系,避免单独查值的多余操作。

4. TreeMap 排序问题与解决

  • 当你用TreeMap存引用数据类型数据,特别是自定义的类对象,它就会报错。报错原因:TreeMap默认自动排序,key 必须具备比较能力,否则会抛出ClassCastException

  • 两种解决方案:

    1. 自定义类实现Comparable接口,重写compareTo方法;
    2. 创建TreeMap时传入Comparator比较器(可用 Lambda / 方法引用简化)。

4. 排序小技巧

这是我遇到的一个小问题,比较浮点型数值用Double.compare(),避免减法运算导致的精度丢失。

三、Set 集合:remove 方法核心用法

Set.remove(Object o)是 Set 的核心删除方法:

  • 作用:删除集合中指定的元素对象,删除成功返回true,元素不存在返回false
  • 重点:Set无索引,不能通过下标删除,底层依靠hashCode()+equals()判断元素是否一致。

四、Lambda 与方法引用:语法糖与延迟执行

这是本周最难但最实用的知识点,理解了匿名内部类→Lambda→方法引用的简化逻辑,以及延迟执行的性能优化意义。

1. 匿名内部类的作用

接口无法直接实例化,但又不想再创建一个类去实现接口。就有了匿名内部类,匿名内部类用于临时一次性实现接口,无需单独创建实现类,是 Lambda 的原始写法。

2. 方法引用的本质

Lambda 的极简语法糖,格式:类名::方法名/对象::方法名,直接复用已有方法,代码更简洁。

3. 延迟执行(核心优化)

  • 有时候,一些操作最终不会被执行,但它的前置操作会执行,从而造成性能浪费。延迟执行就是应对这种情况。
  • 举个例子
//MsgBuilder(函数式接口,核心)
// 函数式接口:用于构建字符串的抽象行为 
public interface MsgBuilder { 
String buildMsg(String... infos); 
}
//PrintUtil.java(核心延迟执行逻辑)
public class PrintUtil { 
// 字符串拼接的核心方法 
   private static String build(String... infos) {        
      StringBuilder builder = new StringBuilder(); 
      for (String info : infos) { 
         builder.append(info); 
       } 
       return builder.toString(); 
    } 
    
    // 核心:延迟执行 - 只有valid为true时,才会执行字符串构建 
    public static void print(boolean valid, String... infos) { 
       if (valid) { // 方法引用(Lambda简化):将构建行为传递,而非直接传递构建结果 
          MsgBuilder builder = PrintUtil::build;        
          System.out.println(builder.buildMsg(infos));
       } 
     } 
  }
public class PrintTest {
    public static void main(String[] args) {
        String name = "Merry"; 
        String desc = "is friendly";
        
        // 场景1:valid=false → 不会执行字符串拼接(无性能损耗) 
        PrintUtil.print(false, name, desc); 
        
        // 场景2:valid=true → 才会执行字符串拼接并打印(延迟执行) 
        PrintUtil.print(true, name, desc);
     }
}
  • 传统写法:字符串提前拼接,即使不打印也会执行,造成性能浪费;
  • Lambda 延迟:将拼接逻辑封装在函数式接口中,仅当需要打印时才执行,从根源避免无效计算。

4. 小小吐槽

可能是我悟性不够吧,但我看的课里在教Lambda延迟执行时,非要扯上方法引用,搞得我很不理解,延迟执行关方法引用啥事。

五、一周学习心得

  1. 核心收获

    • 所有语法糖(Lambda、方法引用)底层逻辑不变,只是简化写法;
    • 泛型、延迟执行都是为了提升代码安全性与性能
    • 集合用法有明确规则,选对遍历方式、排序方式能少踩坑;
  2. 后续方向:深入 Stream 流的中间 / 终结操作、函数式接口实战、集合底层原理。