2024-08-26

在Java中,LinkedList类是一个实现了List接口的双向链表。它允许在近乎O(1)的时间复杂度中进行元素的插入和删除。

以下是一些使用LinkedList的基本操作的示例代码:




import java.util.LinkedList;
 
public class LinkedListExample {
    public static void main(String[] args) {
        // 创建一个空的LinkedList
        LinkedList<Integer> linkedList = new LinkedList<>();
 
        // 添加元素
        linkedList.add(10);
        linkedList.add(20);
        linkedList.add(30);
 
        // 在开始添加元素
        linkedList.addFirst(5);
 
        // 在末尾添加元素
        linkedList.addLast(40);
 
        // 获取并移除第一个元素
        int firstElement = linkedList.removeFirst();
 
        // 获取并移除最后一个元素
        int lastElement = linkedList.removeLast();
 
        // 遍历LinkedList
        for (Integer number : linkedList) {
            System.out.println(number);
        }
 
        // 检查是否包含特定元素
        boolean contains = linkedList.contains(20);
 
        // 获取特定元素的索引
        int index = linkedList.indexOf(30);
 
        // 在特定位置插入元素
        linkedList.add(1, 15);
 
        // 移除特定位置的元素
        int removedElement = linkedList.remove(1);
 
        // 清空LinkedList
        linkedList.clear();
    }
}

这段代码展示了LinkedList的基本操作,包括添加元素、移除元素、获取元素、检查元素是否存在、获取元素索引等。LinkedList是一个非常灵活的数据结构,可以用于各种不同的场景。

2024-08-26

在Java中,可以使用List接口的toArray()方法将List<String>转换为String[]。如果想直接转换为String[]类型,可以在调用toArray()时传入一个String[]类型的空数组作为参数。

以下是转换List<String>String[]的示例代码:




import java.util.ArrayList;
import java.util.List;
 
public class ListToStringArray {
    public static void main(String[] args) {
        // 创建List<String>实例
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");
 
        // 将List<String>转换为String[]
        String[] array = list.toArray(new String[0]);
 
        // 输出转换后的数组
        for (String fruit : array) {
            System.out.println(fruit);
        }
    }
}

在这个例子中,list.toArray(new String[0])会创建一个新的String[]数组,其大小与list的大小相等,并将list中的元素复制到这个新数组中。传入的new String[0]仅用作类型指示,并在内部被转换为正确大小的数组。

2024-08-26

在Java中,List集合去重可以通过多种方式实现,以下是8种常见的去重方法:

  1. 使用Java 8 Stream API的distinct()方法。
  2. 利用HashSet不包含重复元素的特性。
  3. 使用contains()方法遍历比对。
  4. 使用removeIf()方法移除重复元素。
  5. 使用LinkedHashSet保持元素插入顺序。
  6. 使用List.set()方法替换重复元素。
  7. 使用Iterator遍历移除重复元素。
  8. 对象列表按属性去重,可以通过Stream API结合Collectors.toMap()实现。

以下是每种方法的示例代码:




// 示例1:Stream API的distinct()方法
List<Integer> listWithDuplicates = Arrays.asList(1, 2, 3, 2, 1);
List<Integer> distinctList = listWithDuplicates.stream().distinct().collect(Collectors.toList());
 
// 示例2:HashSet去重
Set<Integer> hashSet = new HashSet<>(listWithDuplicates);
List<Integer> hashSetList = new ArrayList<>(hashSet);
 
// 示例3:contains()方法去重
List<Integer> containsList = new ArrayList<>();
for (Integer number : listWithDuplicates) {
    if (!containsList.contains(number)) {
        containsList.add(number);
    }
}
 
// 示例4:removeIf()方法去重
listWithDuplicates.removeIf(listWithDuplicates.subList(1, listWithDuplicates.size()).contains(a)::equals);
 
// 示例5:LinkedHashSet去重并保持顺序
Set<Integer> linkedHashSet = new LinkedHashSet<>(listWithDuplicates);
List<Integer> linkedHashSetList = new ArrayList<>(linkedHashSet);
 
// 示例6:set()方法去重
List<Integer> setList = new ArrayList<>(listWithDuplicates);
for (int i = 0; i < setList.size(); i++) {
    setList.set(i, setList.get(i));
}
 
// 示例7:Iterator去重
Iterator<Integer> iterator = listWithDuplicates.iterator();
while (iterator.hasNext()) {
    Integer number = iterator.next();
    if (listWithDuplicates.indexOf(number) < listWithDuplicates.lastIndexOf(number)) {
        iterator.remove();
    }
}
 
// 示例8:按属性去重
List<Person> people = Arrays.asList(new Person("Alice", 30), new Person("Bob", 25), new Person("Alice", 30));
Map<String, Person> uniqueByName = people.stream()
    .collect(Collectors.toMap(Person::getName, Function.identity(), (existing, replacement) -> existing));
List<Person> uniquePeople = new ArrayList<>(uniqueByName.values());

在示例8中,Person类需要有getName()equals()方法实现,以便正确比较对象的相等性。

注意:示例代码可能需要根据实际情况进行调整,以适应特定的数据类型和需求。

2024-08-26

在Java中,可以使用Arrays.asList()方法和Java Stream API将String转换为List。

使用Arrays.asList():




import java.util.Arrays;
import java.util.List;
 
public class StringToList {
    public static void main(String[] args) {
        String str = "a,b,c";
        List<String> list = Arrays.asList(str.split(","));
        System.out.println(list); // 输出: [a, b, c]
    }
}

使用Java Stream API:




import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class StringToList {
    public static void main(String[] args) {
        String str = "a,b,c";
        List<String> list = Stream.of(str.split(",")).collect(Collectors.toList());
        System.out.println(list); // 输出: [a, b, c]
    }
}

两种方法都可以将以逗号分隔的字符串转换为字符串列表。

2024-08-26

在Java中,可以使用Collectors.groupingBy方法来根据对象的某个字段对列表进行分组。以下是一个简单的例子,演示如何根据对象的某个字段对对象列表进行分组:




import java.util.*;
import java.util.stream.Collectors;
 
class Person {
    String name;
    int age;
 
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    // getter and toString methods for convenience
    public String getName() {
        return name;
    }
 
    public int getAge() {
        return age;
    }
 
    @Override
    public String toString() {
        return "Person{name='" + name + '\'' + ", age=" + age + '}';
    }
}
 
public class GroupByExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 30),
            new Person("Charlie", 25),
            new Person("David", 25),
            new Person("Alice", 20)
        );
 
        Map<Integer, List<Person>> groupedByAge = people.stream()
            .collect(Collectors.groupingBy(Person::getAge));
 
        groupedByAge.forEach((age, persons) -> {
            System.out.println(age + ": " + persons);
        });
    }
}

在这个例子中,我们定义了一个Person类,并创建了一个Person对象的列表。然后我们使用groupingBy收集器根据每个Person对象的age字段对列表进行分组,结果是一个Map,其中键是年龄,值是具有该年龄的所有Person对象的列表。最后,我们遍历这个映射并打印出分组的结果。

2024-08-26

以下是用链表和数组实现栈的示例代码:

链表实现栈:




class ListNode {
    int val;
    ListNode next;
 
    ListNode(int x) {
        val = x;
        next = null;
    }
}
 
class LinkedListStack {
    private ListNode top;
 
    public LinkedListStack() {
        top = null;
    }
 
    public void push(int x) {
        top = new ListNode(x);
        top.next = top;
    }
 
    public int pop() {
        if (top == null) {
            throw new RuntimeException("栈为空");
        }
        int value = top.val;
        top = top.next;
        return value;
    }
 
    public int peek() {
        if (top == null) {
            throw new RuntimeException("栈为空");
        }
        return top.val;
    }
 
    public boolean isEmpty() {
        return top == null;
    }
}

数组实现栈:




class ArrayStack {
    private int[] stack;
    private int top;
 
    public ArrayStack(int size) {
        stack = new int[size];
        top = -1;
    }
 
    public void push(int x) {
        if (top >= stack.length - 1) {
            throw new RuntimeException("栈满");
        }
        stack[++top] = x;
    }
 
    public int pop() {
        if (top < 0) {
            throw new RuntimeException("栈空");
        }
        return stack[top--];
    }
 
    public int peek() {
        if (top < 0) {
            throw new RuntimeException("栈空");
        }
        return stack[top];
    }
 
    public boolean isEmpty() {
        return top == -1;
    }
}

这两个实现都包含了栈的基本操作:入栈(push)、出栈(pop)、查看栈顶元素(peek)和检查栈是否为空(isEmpty)。链表实现栈时,我们使用了循环链表来表示空栈。而数组实现栈时,我们定义了一个top指针来标识栈顶元素的位置。

2024-08-26



public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}
 
public class LinkedListAlgorithm {
 
    // 判断回文链表
    public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) {
            return true;
        }
        ListNode fast = head;
        ListNode slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        ListNode secondHead = reverseList(slow.next);
        ListNode p1 = head;
        ListNode p2 = secondHead;
        while (p2 != null) {
            if (p1.val != p2.val) {
                return false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }
        return true;
    }
 
    // 反转链表
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }
 
    // 判断链表是否有环,并找出环入口
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != slow) {
            if (fast.next == null || fast.next.next == null) {
                return null;
            }
            fast = fast.next.next;
            slow = slow.next;
        }
        fast = head;
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}

这段代码首先定义了一个简单的链表节点类ListNode,然后在LinkedListAlgorithm类中实现了判断回文链表、反转链表以及判断链表是否有环并找出环入口的算法。这些算法是链表问题中的经典算法,对于学习数据结构和算法有重要的教育意义。

2024-08-26

在Java中,可以使用Google Guava库中的Lists.partition方法来对List进行分区。以下是一个简单的例子:




import com.google.common.collect.Lists;
 
import java.util.List;
 
public class PartitionListExample {
    public static void main(String[] args) {
        List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        int partitionSize = 3; // 每个分区的大小
 
        List<List<Integer>> partitionedList = Lists.partition(list, partitionSize);
 
        for (List<Integer> part : partitionedList) {
            System.out.println(part);
        }
    }
}

如果不想使用外部库,可以自己实现分区的逻辑:




import java.util.ArrayList;
import java.util.List;
 
public class CustomPartitionListExample {
    public static void main(String[] args) {
        List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
        int partitionSize = 3; // 每个分区的大小
 
        List<List<Integer>> partitionedList = customPartition(list, partitionSize);
 
        for (List<Integer> part : partitionedList) {
            System.out.println(part);
        }
    }
 
    public static List<List<Integer>> customPartition(List<Integer> list, int partitionSize) {
        List<List<Integer>> partitions = new ArrayList<>();
        int listSize = list.size();
        for (int i = 0; i < listSize; i += partitionSize) {
            partitions.add(new ArrayList<>(list.subList(i, Math.min(i + partitionSize, listSize))));
        }
        return partitions;
    }
}

在这个例子中,customPartition方法接受一个List和分区大小作为参数,然后返回一个包含了分区后的List的List。

2024-08-26



public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}
 
public class LinkedListAlgorithm {
 
    // 删除有序链表中值相同的节点
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null) {
            return head;
        }
        ListNode current = head;
        while (current.next != null) {
            if (current.val == current.next.val) {
                current.next = current.next.next;
            } else {
                current = current.next;
            }
        }
        return head;
    }
 
    // 合并两个有序链表
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        } else if (l2 == null) {
            return l1;
        }
        ListNode dummy = new ListNode(0);
        ListNode current = dummy;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                current.next = l1;
                l1 = l1.next;
            } else {
                current.next = l2;
                l2 = l2.next;
            }
            current = current.next;
        }
        if (l1 != null) {
            current.next = l1;
        }
        if (l2 != null) {
            current.next = l2;
        }
        return dummy.next;
    }
 
    // 合并k个有序链表
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        ListNode dummy = new ListNode(0);
        ListNode current = dummy;
        PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>() {
            @Override
            public int compare(ListNode o1, ListNode o2) {
                return o1.val - o2.val;
            }
        });
        for (ListNode head : lists) {
            if (head != null) {
                pq.add(head);
            }
        }
        while (!pq.isEmpty()) {
            ListNode
2024-08-26

在Java中,可以使用Java 8引入的Stream API将List转换为Map。以下是几种常见的方法:

  1. 使用Collectors.toMap方法,当List中的对象具有唯一的键值时,可以使用此方法。



List<Item> list = new ArrayList<>();
// 假设Item有id和name两个属性
Map<Integer, Item> map = list.stream()
    .collect(Collectors.toMap(Item::getId, item -> item));
  1. 如果List中的对象不唯一,并且想要合并值,可以使用重载的toMap方法,提供合并函数。



List<Item> list = new ArrayList<>();
Map<Integer, String> map = list.stream()
    .collect(Collectors.toMap(Item::getId, Item::getName, (v1, v2) -> v1 + "," + v2));
  1. 使用groupingBy收集器进行分组,得到的Map的值将是一个List。



List<Item> list = new ArrayList<>();
Map<Integer, List<Item>> map = list.stream()
    .collect(Collectors.groupingBy(Item::getId));

确保在使用toMap时List中的键不能重复,否则会抛出IllegalStateException。如果可能存在重复的键,可以使用第二种方法来合并值。