2024-08-27

要将List集合转换为树形结构,通常需要一个树形结构的实体类,该类包含了父子关系的标识。以下是一个简单的示例,假设我们有一个实体类TreeNode,它有一个id和一个parentId字段,以及用于子节点的children列表:




import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
 
class TreeNode {
    int id;
    int parentId;
    List<TreeNode> children;
 
    TreeNode(int id, int parentId) {
        this.id = id;
        this.parentId = parentId;
        this.children = new ArrayList<>();
    }
}
 
public class ListToTree {
 
    public static List<TreeNode> listToTree(List<TreeNode> nodes) {
        Map<Integer, TreeNode> nodeMap = new HashMap<>();
        for (TreeNode node : nodes) {
            nodeMap.put(node.id, node);
        }
 
        List<TreeNode> rootNodes = nodes.stream()
                .filter(node -> node.parentId == -1) // 假设-1表示根节点
                .collect(Collectors.toList());
 
        for (TreeNode parent : rootNodes) {
            addChild(nodeMap, parent);
        }
 
        return rootNodes;
    }
 
    private static void addChild(Map<Integer, TreeNode> nodeMap, TreeNode parent) {
        List<TreeNode> children = nodes.stream()
                .filter(node -> node.parentId == parent.id)
                .collect(Collectors.toList());
 
        for (TreeNode child : children) {
            parent.children.add(child);
            addChild(nodeMap, child);
        }
    }
 
    public static void main(String[] args) {
        // 示例数据
        List<TreeNode> nodes = Arrays.asList(
                new TreeNode(1, -1),
                new TreeNode(2, 1),
                new TreeNode(3, 1),
                new TreeNode(4, 2),
                new TreeNode(5, -1)
        );
 
        List<TreeNode> tree = listToTree(nodes);
        // 打印结果
        for (TreeNode node : tree) {
            System.out.println(node);
        }
    }
}

在这个例子中,listToTree方法首先创建了一个映射,用于快速访问所有节点。然后,它找到所有根节点(在这个例子中,根节点的parentId被假设为-1),并递归地为每个根节点添加子节点。最后,返回根节点列表构成的树。

2024-08-27

在Java中,可以使用Arrays.asList()方法将数组转换为List集合。这里有一个简单的例子:




import java.util.Arrays;
import java.util.List;
 
public class ArrayToListExample {
    public static void main(String[] args) {
        // 创建一个数组
        String[] array = {"Element1", "Element2", "Element3"};
 
        // 使用Arrays.asList()将数组转换为List集合
        List<String> list = Arrays.asList(array);
 
        // 输出List集合
        System.out.println(list);
    }
}

注意:Arrays.asList()返回的是固定大小的List,如果尝试添加或删除元素,将会抛出UnsupportedOperationException异常。如果需要一个可变的List,可以创建一个新的ArrayList:




List<String> modifiableList = new ArrayList<>(Arrays.asList(array));
2024-08-27

在Java中,ArrayList是一个动态数组,用于存储对象引用序列。以下是ArrayList的一些核心方法的简化版本源代码,以解释其工作原理:




public class ArrayList<E> {
    private Object[] elementData;
    private int size;
 
    public ArrayList() {
        this(10); // 默认初始容量为10
    }
 
    public ArrayList(int initialCapacity) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
        this.elementData = new Object[initialCapacity];
    }
 
    public boolean add(E e) {
        ensureCapacity(size + 1);  // 确保数组有足够空间
        elementData[size++] = e;   // 添加元素并增加size
        return true;
    }
 
    public E get(int index) {
        rangeCheck(index);
        return (E) elementData[index];  // 返回指定位置的元素
    }
 
    private void ensureCapacity(int minCapacity) {
        if (minCapacity - elementData.length > 0) {
            grow(minCapacity);  // 如果需求容量大于当前数组长度,进行扩容
        }
    }
 
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);  // 新容量为旧容量的1.5倍
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        elementData = Arrays.copyOf(elementData, newCapacity);  // 复制到新数组
    }
 
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
    }
}

这个简化版本的ArrayList展示了数组动态扩展的基本原理。当添加元素时,如果数组已满,则通过grow方法创建一个新的数组,并将旧数组的内容复制到新数组。这种方式使得ArrayList可以在添加大量元素时自动管理内存。

2024-08-27

Lists.newArrayList是Guava库提供的一个方便的方法,用于创建一个类型安全的ArrayList。而new ArrayList()是Java原生的方式。

区别如下:

  1. 类型安全:使用Lists.newArrayList创建的列表是类型安全的,意味着你可以在创建时指定列表中元素的类型,这样编译器可以在编译时进行类型检查。而new ArrayList()不是类型安全的,需要在运行时进行类型检查。
  2. 初始容量:Lists.newArrayList可以接收一个初始容量参数,如果你知道大概需要多少元素,可以提供一个初始容量,这样可以减少重新分配的次数,从而提高性能。new ArrayList()则不可以。
  3. 导入:使用Lists.newArrayList需要导入Guava库,而new ArrayList()是Java基础库的一部分,不需要额外导入。

示例代码:




// 使用Lists.newArrayList
import com.google.common.collect.Lists;
List<String> listWithGuava = Lists.newArrayList(); // 类型安全,无初始容量
List<String> listWithGuavaAndInitialCapacity = Lists.newArrayListWithCapacity(10); // 类型安全,有初始容量
 
// 使用new ArrayList()
import java.util.ArrayList;
ArrayList<String> listWithJava = new ArrayList<>(); // 非类型安全,无初始容量
ArrayList<String> listWithJavaAndInitialCapacity = new ArrayList<>(10); // 非类型安全,有初始容量

如果不需要Guava库提供的额外功能,并且项目中没有使用Guava库,那么应该使用new ArrayList()以减少依赖。如果项目中已经在使用Guava库,为了代码的一致性和类型安全,可以选择Lists.newArrayList

2024-08-27

以下是一个简单的 Java 代码示例,演示了如何实现单链表的核心 API 方法,包括节点类定义、单链表类定义以及添加节点的方法。




public class LinkedList {
    private Node head;
 
    private static class Node {
        int value;
        Node next;
 
        Node(int value) {
            this.value = value;
            this.next = null;
        }
    }
 
    public void add(int value) {
        Node newNode = new Node(value);
        if (head == null) {
            head = newNode;
        } else {
            Node current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
        }
    }
 
    // 其他核心API方法,如插入、删除、查找等
}

这个示例中,我们定义了一个LinkedList类,它有一个私有内部类Node,代表链表节点。add方法用于在链表末尾添加新节点。这个实现没有包括其他复杂的逻辑,如插入、删除、查找等操作,因为这会使代码变得冗长而且不利于理解。核心的添加节点功能已经被实现,这有助于开发者理解单链表的基本概念。

2024-08-27

在Java中,获取List中的最后一个元素可以通过几种方式实现。以下是几种常见的方法:

  1. 使用get(int index)方法,索引是list.size() - 1
  2. 使用list.get(list.size() - 1)
  3. 使用Java 8的Stream API中的reduce方法。

以下是使用这些方法的示例代码:




import java.util.List;
import java.util.Arrays;
 
public class LastElement {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
 
        // 方法1: 使用get(int index)
        Integer lastElement1 = list.get(list.size() - 1);
        System.out.println(lastElement1); // 输出: 5
 
        // 方法2: 使用list.size() - 1
        Integer lastElement2 = list.get(list.size() - 1);
        System.out.println(lastElement2); // 输出: 5
 
        // 方法3: 使用Stream API的reduce
        Integer lastElement3 = list.stream().reduce((first, second) -> second).orElse(null);
        System.out.println(lastElement3); // 输出: 5
    }
}

请注意,使用get(int index)方法时,如果索引超出范围将抛出IndexOutOfBoundsException异常。因此,在实际应用中,可能需要先检查list.size()是否大于0。

2024-08-27



// 定义一个链表节点类
class ListNode {
  constructor(value) {
    this.val = value;
    this.next = null;
  }
}
 
// 创建链表
function createLinkedList(arr) {
  let head = null;
  for (let i = arr.length - 1; i >= 0; i--) {
    head = new ListNode(arr[i]);
    head.next = newListHead;
  }
  return head;
}
 
// 打印链表
function printLinkedList(head) {
  let current = head;
  while (current) {
    console.log(current.val);
    current = current.next;
  }
}
 
// 示例:创建并打印链表
const arr = [1, 2, 3, 4, 5];
const head = createLinkedList(arr);
printLinkedList(head);

这段代码首先定义了一个链表节点类ListNode,然后提供了一个函数createLinkedList来根据一个数组创建链表,并返回链表头节点。printLinkedList函数用于打印链表中的每个节点值。最后,示例中创建了一个链表并打印了它的所有节点值。

2024-08-27

在Java中,List是一个很常用的集合类,以下是List中常见的几个方法以及五种遍历方式的示例代码:

  1. add(E e):向列表的尾部添加指定的元素(可选操作)。
  2. remove(int index):删除列表中指定位置的元素(可选操作)。
  3. get(int index):返回列表中指定位置的元素。
  4. set(int index, E element):用指定元素替换列表中指定位置的元素(可选操作)。
  5. size():返回列表的元素个数。

以下是五种遍历List的方式:

  1. 使用for循环:



List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}
  1. 使用迭代器:



List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
  1. 使用增强for循环:



List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
for (String s : list) {
    System.out.println(s);
}
  1. 使用Java 8的流(Stream)API:



List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.stream().forEach(System.out::println);
  1. 使用List的forEach方法(Java 8及以上):



List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.forEach(System.out::println);
2024-08-27

removeIf 方法是 Java 8 引入的,它允许你通过传递一个 Predicate 接口实现来移除符合条件的元素。这是一个简单的例子:




import java.util.ArrayList;
import java.util.List;
 
public class RemoveIfExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
 
        // 移除所有偶数
        numbers.removeIf(n -> n % 2 == 0);
 
        System.out.println(numbers); // 输出: [1, 3, 5]
    }
}

在这个例子中,removeIf 方法接收了一个 lambda 表达式 n -> n % 2 == 0 作为参数,该表达式用于检查列表中的每个元素是否为偶数。如果是偶数,则将其从列表中移除。

2024-08-27



import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
 
public class ListSortExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("banana", "apple", "pear", "orange");
 
        // 使用Comparator.comparing根据字符串长度进行排序
        List<String> sortedList = list.stream()
                .sorted(Comparator.comparing(String::length))
                .collect(Collectors.toList());
 
        // 输出排序结果
        sortedList.forEach(System.out::println);
    }
}

这段代码首先创建了一个包含几个字符串的列表,然后使用Java 8的Stream API对其进行排序。Comparator.comparing(String::length)是一个比较器,它根据字符串的长度来比较两个字符串。排序后的列表被输出。这个例子展示了如何使用Java 8的新特性来对列表进行排序。