Bootstrap

一些java中记忆的问题

什么是封装

封装是将对象的属性和方法(或称为成员)结合成一个独立的单元,隐藏对象的属性和实现细节,仅对外公开接口(方法)与对象进行交互。

链表数据结构

链表是一种常见的数据结构,它由一系列节点(Node)组成,每个节点包含数据和一个或多个指向其他节点的引用(即指针)。与数组不同,链表中的元素在内存中不是连续存储的。链表提供了一种灵活的方式来组织数据,尤其适用于需要频繁插入和删除操作的场景。

链表的类型

  1. 单向链表(Singly Linked List)

    • 每个节点包含数据和一个指向下一个节点的引用。
    • 最后一个节点的引用指向 null,表示链表的结束。
  2. 双向链表(Doubly Linked List)

    • 每个节点包含数据、一个指向下一个节点的引用和一个指向前一个节点的引用。
    • 链表的头节点的前引用和尾节点的后引用指向 null
  3. 循环链表(Circular Linked List)

    • 单向或双向链表的一种变体,其中最后一个节点的引用指向头节点,形成一个环。
  4. 双向循环链表(Doubly Circular Linked List)

    • 双向链表的一种变体,最后一个节点的后引用指向头节点,头节点的前引用指向尾节点。

单向链表的实现示例

以下是一个简单的单向链表的实现:

class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
        this.next = null;
    }
}

class SinglyLinkedList {
    Node head;

    // 添加元素到链表的头部
    public void addFirst(int data) {
        Node newNode = new Node(data);
        newNode.next = head;
        head = newNode;
    }

    // 添加元素到链表的尾部
    public void addLast(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
            return;
        }
        Node current = head;
        while (current.next != null) {
            current = current.next;
        }
        current.next = newNode;
    }

    // 打印链表中的所有元素
    public void printList() {
        Node current = head;
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }
}

public class Main {
    public static void main(String[] args) {
        SinglyLinkedList list = new SinglyLinkedList();
        list.addFirst(1);
        list.addLast(2);
        list.addLast(3);
        list.printList();  // 输出: 1 2 3
    }
}

链表的优点

  1. 动态大小:链表可以动态调整大小,没有固定的容量限制。
  2. 插入和删除效率高:在已知位置插入或删除元素的时间复杂度为O(1)。
  3. 内存利用率高:链表的内存利用率比数组高,因为不需要预先分配大量连续内存。

链表的缺点

  1. 访问效率低:链表不支持高效的随机访问,访问任意元素的时间复杂度为O(n)。
  2. 额外的内存开销:每个节点除了存储数据外,还需要存储指向下一个节点的引用,增加了内存开销。
  3. 复杂的实现:与数组相比,链表的实现和操作更复杂,需要处理指针的维护。

链表的应用场景

  1. 频繁插入和删除操作:例如实现队列、栈等数据结构。
  2. 需要动态调整大小的场景:例如实现链式散列表(Hash Table)。
  3. 内存利用率要求高的场景:例如大数据处理中的内存管理。

arrylist vector linklist 的区别

ArrayListVectorLinkedList 是 Java 中常用的集合类,它们都有各自的特性和用途。以下是它们之间的主要区别:

1. ArrayList

  • 底层实现:基于动态数组。
  • 线程安全:不是线程安全的,多个线程同时访问时需要手动同步。
  • 性能:由于是动态数组,支持快速随机访问(时间复杂度为 O(1)),但在插入和删除元素时,特别是在数组中间位置,会涉及大量元素的移动,性能较低(时间复杂度为 O(n))。
  • 适用场景:适用于频繁读取和访问元素的场景。

2. Vector

  • 底层实现:基于动态数组。
  • 线程安全:线程安全的,所有方法都被 synchronized 修饰,多个线程可以安全地访问。
  • 性能:由于线程安全的开销,性能比 ArrayList 略低。同样支持快速随机访问,但插入和删除元素时性能较低。
  • 适用场景:适用于多线程环境下,需要频繁读取和访问元素的场景。

3. LinkedList

  • 底层实现:基于双向链表。
  • 线程安全:不是线程安全的,多个线程同时访问时需要手动同步。
  • 性能:不支持高效的随机访问(时间复杂度为 O(n)),但在插入和删除元素时,性能较高(在链表两端操作的时间复杂度为 O(1),在中间插入删除的时间复杂度为 O(n))。
  • 适用场景:适用于频繁插入和删除元素的场景。

具体区别总结

  • 实现方式ArrayListVector 基于动态数组实现,而 LinkedList 基于双向链表实现。
  • 线程安全Vector 是线程安全的,ArrayListLinkedList 不是线程安全的。
  • 性能ArrayListVector 提供了快速的随机访问,但插入和删除性能较低;LinkedList 插入和删除性能较高,但随机访问性能较低。
  • 内存使用ArrayListVector 的内存使用更加紧凑,LinkedList 由于每个节点需要存储指针,内存开销较大。

使用示例

import java.util.ArrayList;
import java.util.Vector;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        // ArrayList 示例
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("A");
        arrayList.add("B");
        System.out.println("ArrayList: " + arrayList);

        // Vector 示例
        Vector<String> vector = new Vector<>();
        vector.add("A");
        vector.add("B");
        System.out.println("Vector: " + vector);

        // LinkedList 示例
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("A");
        linkedList.add("B");
        System.out.println("LinkedList: " + linkedList);
    }
}

选择哪种集合类,取决于具体的使用场景和需求。

迭代器 简述

迭代器(Iterator)是Java集合框架中的一种对象,用于遍历集合(如ArrayListHashSet等)中的元素。它提供了一种统一的方式来访问集合中的每一个元素,而不需要了解集合的底层实现。以下是迭代器的主要特性和使用方法:

主要特性

  1. 遍历集合:迭代器可以遍历集合中的每一个元素。
  2. 无须了解底层实现:使用迭代器时,不需要知道集合的具体实现方式,只需要按照统一的接口操作。
  3. 单向遍历:迭代器通常只能单向遍历集合,从第一个元素开始,一直到最后一个元素。
  4. 安全删除:通过迭代器,可以在遍历过程中安全地删除元素。

常用方法

迭代器接口 (java.util.Iterator) 提供了以下三个主要方法:

  1. boolean hasNext():如果迭代器中还有元素可以迭代,则返回 true
  2. E next():返回迭代器中的下一个元素。
  3. void remove():从集合中删除迭代器返回的上一个元素(可选操作)。

使用示例

以下是使用迭代器遍历 ArrayList 的一个简单示例:

import java.util.ArrayList;
import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        // 获取迭代器
        Iterator<String> iterator = list.iterator();

        // 使用迭代器遍历集合
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
        }
    }
}

迭代器的优势

  1. 统一遍历方式:无论集合类型是什么,使用迭代器都可以统一地遍历集合。
  2. 避免并发修改异常:在遍历过程中,如果使用集合自身的修改方法(如addremove),可能会导致 ConcurrentModificationException。使用迭代器的 remove 方法可以安全地删除元素。
  3. 简化代码:迭代器可以简化代码,使得遍历集合的代码更加清晰和简洁。

注意事项

  • 只读迭代器:对于某些集合(如Collections.unmodifiableList返回的集合),迭代器可能是只读的,调用 remove 方法会抛出 UnsupportedOperationException
  • 并发修改:如果在迭代过程中修改了集合(不是通过迭代器),可能会导致 ConcurrentModificationException。要在遍历过程中安全地修改集合,应该使用迭代器的 remove 方法。

jdk1.8新特性

JDK 1.8(也称为Java 8)引入了许多新特性和改进,使其成为Java平台的一个重要版本。以下是一些主要的新特性:

  1. Lambda 表达式

    • Lambda 表达式提供了一种简洁的方式来传递行为,使代码更简洁和灵活。
    • 语法:(参数) -> 表达式 (参数) -> { 代码块 }
    • 例如:(int x, int y) -> x + y 表示一个接收两个整数并返回它们和的函数。
  2. 函数式接口

    • 函数式接口是仅包含一个抽象方法的接口,用于Lambda表达式和方法引用。
    • Java 8 提供了许多内置的函数式接口,如 Function<T, R>, Consumer<T>, Supplier<T>, Predicate<T> 等。
    • 可以用 @FunctionalInterface 注解来标识函数式接口。
  3. 方法引用

    • 方法引用提供了一种简洁的Lambda表达式的替代语法。
    • 语法:Class::methodNameinstance::methodName
    • 例如:String::valueOf 表示 valueOf 静态方法的引用。
  4. 接口默认方法

    • 接口现在可以有默认方法,允许在不破坏现有实现的情况下添加新方法。
    • 使用 default 关键字来定义默认方法。
    • 例如:default void log(String message) { System.out.println(message); }
  5. Stream API

    • Stream API 用于处理集合类(如List、Set)的数据操作。
    • 支持对集合进行声明性的数据处理,如过滤、排序、映射等。
    • 例如:List<String> filteredList = list.stream().filter(s -> s.startsWith("a")).collect(Collectors.toList());
  6. Optional 类

    • Optional 类用于防止出现空指针异常。
    • 提供了许多方法来安全地处理可能为空的值。
    • 例如:Optional<String> optional = Optional.ofNullable(value);
  7. 新的日期时间 API

    • 引入了 java.time 包,提供了更好的日期时间处理。
    • 包括 LocalDate, LocalTime, LocalDateTime, ZonedDateTime 等类。
    • 例如:LocalDate date = LocalDate.now();
  8. Nashorn JavaScript 引擎

    • Java 8 引入了 Nashorn,一个新的 JavaScript 引擎,用于替代 Rhino。
    • 允许在 Java 应用中嵌入 JavaScript 代码。
  9. Base64 编码和解码

    • 提供了 java.util.Base64 类用于Base64编码和解码。
    • 例如:String encoded = Base64.getEncoder().encodeToString("hello".getBytes());
  10. 并行数组(Parallel Array)

    • 提供了 Arrays.parallelSort 方法,用于并行排序数组,提高大数据集的处理性能。
  11. 改进的集合 API

    • 添加了一些新的方法,如 forEachremoveIfreplaceAllcomputemerge 等。
;