Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap

概述

1、集合可以看作是一个容器,如金丝猴可以看作是一个集合。
2、java.util 包中提供了一些集合类,这些集合类又被称为容器。提到容器不难想到数组。集合类与数组的不同之处是:数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型的数据,集合用来存放对象的引用。
Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第1张图片

一、常用类的集合关系

用来存放对象的引用。常用的集合有 List 集合、Set 集合和 Map 集合,其中 List 集合与 Set 集合继承了Collection 接口,各接口还提供了不同的实现类。上述集合类的继承关系如下图所示。
Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第2张图片

二、Collection接口

======================================================================================================================
方法													功能描述
----------------------------------------------------------------------------------------------------------------------
add(E e)						将指定的对象添加到该集合中
remove(Object o)				将指定的对象从该集合中移除
isEmpty()						返回 boolean 值,用于判断当前集合是否为空
iterator()						返回在此 Collection 的元素上进行迭代的迭代器。用于遍历集合中的对象
size()							返回 int 型值,获取该集合中元素的个数

如何遍历集合中的每个元素呢? 通常遍历集合,都是通过迭代器 (Iterator) 来实现。Collection 接口中的iterator()方法可返回在此 Collection 进行选代的迭代器。下面的实例就是典型的遍历集合的方法。

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

public class Test {
    public static void main(String[] args) {
        Collection<String> list = new ArrayList<>();//创建一个ArrayList类型对象
        System.out.println("添加元素前,集合list是否为空:"+list.isEmpty());//使用isEmpty()方法判断集合是否为空

        list.add("a1");//使用add()方法向集合添加数据
        list.add("a2");
        list.add("a3");

        System.out.println("添加元素后,集合list是否为空:"+list.isEmpty());
        System.out.println("集合list的长度:"+list.size());//使用size()方法获取集合的长度

        Iterator<String> iterator01 = list.iterator();//使用iterator()获取元素在集合上的迭代器,用于遍历集合中的元素

        System.out.println("==========移除元素前输出==========");

        while(iterator01.hasNext()){
            String str = (String) iterator01.next();//Iterator的next()放回的是Object
            System.out.println(str);
        }

        System.out.println("==========移除元素后输出==========");

        list.remove("a2");//使用remove()移除集合中的元素
        iterator01 = list.iterator();
        while(iterator01.hasNext()){
            String str = (String) iterator01.next();//Iterator的next()放回的是Object
            System.out.println(str);
        }
    }
}

Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第3张图片

三、List集合

3.1、ArrayList

ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。

import java.util.*;

public class Test {
    public static void main(String[] args) {
        List<String> strList = new ArrayList<String>();

        strList.add("a1");
        strList.add("a2");
        strList.add("a3");
        strList.add("a4");
        System.out.println("ArrayList输出strList.get(1):" + strList.get(1));//使用get()获取索引对应的值

        strList.set(0, "b1");//使用set()修改索引对应的值
        strList.remove(2);//使用remove()移除索引对应的值
        strList.remove("a4");//使用remove()移除指定对象

        for (int i=0;i<strList.size();i++){//使用size()获取集合长度
            System.out.println("=======" + strList.get(i));
        }
    }
}

Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第4张图片

3.2、LinkedList

LinkedList 实现了 Queue 接口,可作为队列使用。
LinkedList 实现了 List 接口,可进行列表的相关操作。
LinkedList 实现了 Deque 接口,可作为队列使用。
LinkedList 实现了 Cloneable 接口,可实现克隆。

import java.util.*;

public class Test{
    public static void main(String[] args) {
        List<String> strList = new LinkedList<String>();
        

        strList.add("a1");
        strList.add("a2");
        strList.add("a4");
        System.out.println("LinkedList输出strList.get(1):" + strList.get(1));//使用get()获取索引对应的值

        strList.set(0, "b1");//使用set()修改索引对应的值
        strList.remove(2);//使用remove()移除索引对应的值
        strList.remove("a4");//使用remove()移除指定对象

        for (int i=0;i<strList.size();i++){//使用size()获取集合长度
            System.out.println("=======" + strList.get(i));
        }
    }
}

Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第5张图片

// 使用 addFirst() 在头部添加元素
strList.addFirst("Wiki"); 
// 使用 addLast() 在尾部添加元素
sites.addLast("Wiki");

// 使用 removeFirst() 移除头部元素
sites.removeFirst();
// 使用 removeLast() 移除尾部元素
sites.removeLast();

// 使用 getFirst() 获取头部元素
        sites.getFirst();
        // 使用 getLast() 获取尾部元素
        sites.getLast();
        
//使用 for-each 来迭代元素
for (String i : sites) {
    System.out.println(i);
}

3.3、List集合的四种遍历方式

class test {
    public static void main(String[] args) {
        List<String> strList = new ArrayList<String>();
        //或
        // List strList = new LinkedList();

        strList.add("a1");
        strList.add("a2");
        strList.add("a3");
        strList.add("a4");

        //遍历方式一:foreach增强循环遍历集合
        System.out.println("遍历方式一===============");
        for (String str : strList) {
            System.out.println(str);
        }

        //遍历方式二:for循环遍历集合
        System.out.println("遍历方式二===============");
        for (int i = 0; i < strList.size(); i++) {//使用size()获取集合长度
            System.out.println(strList.get(i));
        }

        //遍历方式三:迭代器遍历集合
        System.out.println("遍历方式三===============");
        Iterator<String> iterator = strList.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //遍历方式四:lambda两种方法遍历
        System.out.println("遍历方式四===============");
        System.out.println("=====lambda遍历方式一======");
        strList.forEach(n->System.out.println(n));

        System.out.println("=====lambda遍历方式二======");
        strList.forEach(System.out::println);
    }
}

//运行结果
遍历方式一===============
a1
a2
a3
a4
遍历方式二===============
a1
a2
a3
a4
遍历方式三===============
a1
a2
a3
a4
遍历方式四===============
=====lambda遍历方式一======
a1
a2
a3
a4
=====lambda遍历方式二======
a1
a2
a3
a4

四、Set集合

4.1、HashSet

HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
HashSet 允许有 null 值。
HashSet 是无序的,即不会记录插入的顺序。
HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。

import java.util.*;

public class Test {
    public static void main(String[] args) {
        HashSet<String> sites = new HashSet<String>();

        sites.add("Google");    //使用add()方法添加对象到集合
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");    // 重复的元素不会被添加

        System.out.println("删除元素前集合:" + sites);

        //判断元素是否存在
        System.out.println("判断元素'Taobao'是否存在" + sites.contains("Taobao"));
        System.out.println("判断元素'Taobao001'是否存在" + sites.contains("Taobao001"));

        System.out.println("可以使用 for-each 来迭代 HashSet 中的元素。");
        for (String i : sites) {
            System.out.println(i);
        }

        sites.remove("Taobao");  // 删除元素,删除成功返回 true,否则为 false
        System.out.println("删除元素后集合:" + sites);

        sites.clear();  //删除集合中所有元素可以使用clear方法:
        //如果要计算 HashSet 中的元素数量可以使用 size() 方法:
        System.out.println("使用clear方法删除集合中所有元素后集合大小:" + sites.size());
    }
}

Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第6张图片

4.2、TreeSet

1、集合中的元素没有重复
2、集合中的元素不保证插入顺序,而是默认使用元素的自然排序,不过可以自定义排序器
3、jdk8以后,集合中的元素不可以是null
4、集合不是线程安全
5、相对于HashSet, 性能更差
TreeSet是Java中的一个有序集合,它基于红黑树(红黑二叉搜索树)实现。TreeSet中的元素是按照自然顺序进行排序的,或者根据自定义的Comparator进行排序。

以下是TreeSet的一些基本特点和使用方法:

  1. 创建TreeSet对象:

    TreeSet<ElementType> treeSet = new TreeSet<>();
    
  2. 添加元素:

    treeSet.add(element);
    
  3. 删除元素:

    treeSet.remove(element);
    
  4. 获取第一个元素:

    ElementType firstElement = treeSet.first();
    
  5. 获取最后一个元素:

    ElementType lastElement = treeSet.last();
    
  6. 获取小于等于给定元素的最大元素:

    ElementType floorElement = treeSet.floor(element);
    
  7. 获取大于等于给定元素的最小元素:

    ElementType ceilingElement = treeSet.ceiling(element);
    
  8. 遍历元素:

    for (ElementType element : treeSet) {
        // 处理元素
    }
    

需要注意的是,TreeSet要求集合中的元素实现Comparable接口,或者在创建TreeSet时提供自定义的Comparator来指定元素的比较规则。如果元素不具备自然顺序,并且没有自定义的Comparator,将会抛出ClassCastException异常。

TreeSet的元素是唯一的,不允许重复。当插入重复元素时,插入操作将被忽略。

TreeSet的底层实现是红黑树,它提供了高效的插入、删除和查找操作。因为有序性的特点,TreeSet在需要按照一定顺序遍历元素或进行范围查询的场景通常更合适。

4.3、Set集合的三种遍历方式

class test {
    public static void main(String[] args) {
        HashSet<String> sites = new HashSet<String>();

        sites.add("Google");    //使用add()方法添加对象到集合
        sites.add("Runoob");
        sites.add("Taobao");
        sites.add("Zhihu");
        sites.add("Runoob");    // 重复的元素不会被添加

        //遍历方式一:foreach增强循环遍历集合
        System.out.println("遍历方式一===============");
        for (String i : sites) {
            System.out.println(i);
        }

        //遍历方式二:Iterator迭代遍历
        System.out.println("遍历方式二===============");
        Iterator<String> it = sites.iterator();
        while (it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }

        //遍历方式三:lambda两种方法遍历
        System.out.println("遍历方式三===============");
        System.out.println("=====lambda遍历方式一======");
        sites.forEach(n->System.out.println(n));

        System.out.println("=====lambda遍历方式二======");
        sites.forEach(System.out::println);
    }
}

//运行结果
遍历方式一===============
Google
Runoob
Zhihu
Taobao
遍历方式二===============
Google
Runoob
Zhihu
Taobao
遍历方式三===============
=====lambda遍历方式一======
Google
Runoob
Zhihu
Taobao
=====lambda遍历方式二======
Google
Runoob
Zhihu
Taobao

五、Map集合

Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第7张图片

5.1、HashMap

1、HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
2、HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,
3、最多允许一条记录的键为 null。
4、不支持线程同步。
5、HashMap 是无序的,即不会记录插入的顺序。

import java.util.*;

public class Test001 {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");

        System.out.println("初始HashMap集合:" + Sites);

        //使用 get(key) 方法来获取 key 对应的 value:
        System.out.println(Sites.get(3));

        //使用 remove(key) 方法来删除 key 对应的键值对(key-value):
        Sites.remove(4);
        System.out.println("删除HashMap集合中key=4对应的值后的HashMap集合:" + Sites);

        //计算 HashMap 中的元素数量可以使用 size() 方法
        System.out.println("HashMap 中的元素数量:" + Sites.size());

        //使用 for-each 来迭代 HashMap 中的元素
        // 输出 key 和 value
        for (Integer i : Sites.keySet()) {
            System.out.println("key: " + i + " value: " + Sites.get(i));
        }
        // 返回所有 value 值
        for(String value: Sites.values()) {
            // 输出每一个value
            System.out.print(value + ", ");
        }

        //删除所有键值对(key-value)可以使用 clear 方法:
        Sites.clear();
        System.out.println("\n使用 clear 方法删除所有键值对:" + Sites);
    }
}

Java029—Java常用集合类概述ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap_第8张图片

5.2、TreeMap

Java中的TreeMap是一种基于红黑树实现的有序映射表,它继承自AbstractMap类,并实现了NavigableMap接口。TreeMap中的键值对是按照键的自然顺序进行排序的,或者通过自定义比较器进行排序。

下面是一些TreeMap的基本操作和使用方法:

  1. 创建TreeMap对象:

    TreeMap<KeyType, ValueType> treeMap = new TreeMap<>();
    
  2. 添加元素:

    treeMap.put(key, value);
    
  3. 获取元素:(根据键来获取)

    ValueType value = treeMap.get(key);
    
  4. 删除元素:(根据键来删除)

    treeMap.remove(key);
    
  5. 判断键是否存在:

    boolean containsKey = treeMap.containsKey(key);
    
  6. 判断值是否存在:

    boolean containsValue = treeMap.containsValue(value);
    
  7. 获取键的集合:

    Set<KeyType> keySet = treeMap.keySet();
    
  8. 获取值的集合:

    Collection<ValueType> values = treeMap.values();
    
  9. 遍历元素:

    for (Map.Entry<KeyType, ValueType> entry : treeMap.entrySet()) {
        KeyType key = entry.getKey();
        ValueType value = entry.getValue();
        // 处理键值对
    }
    

TreeMap还提供了一些其他有用的方法,如获取第一个键、最后一个键等,还可以根据键获取小于等于指定键的最大键和大于等于指定键的最小键。此外,TreeMap还可以通过自定义比较器来实现自定义排序。

需要注意的是,TreeMap不允许键为null,如果插入null键会抛出NullPointerException异常。如果需要使用可空键,可以考虑使用另外的映射表实现,如HashMap。

class test {
    public static void main(String[] args) throws IOException {
        //1. 创建TreeMap对象:
        TreeMap<Integer, String> treeMap = new TreeMap<>();

        //2. 添加元素:
        treeMap.put(16, "a");
        treeMap.put(1, "b");
        treeMap.put(4, "c");
        treeMap.put(3, "d");
        treeMap.put(8, "e");
        treeMap.put(20, "f");

        //3. 获取元素:(根据键来获取)
        String value1 = treeMap.get(3);
        System.out.println("获取键为3对应的值为:" + value1);

        //遍历元素:方式1
        System.out.println("删除元素前=========================");
        treeMap.forEach((key, value) -> {
            System.out.println("key: " + key + ", value: " + value);
        });

        //4. 删除元素:(根据键来删除)
        treeMap.remove(20);

        //5. 判断键是否存在:
        boolean containsKey  = treeMap.containsKey(8);
        //6. 判断值是否存在:
        boolean containsValue = treeMap.containsValue("f");
        System.out.println("键‘8’是否存在:"+containsKey+" ,值‘f’是否存在:"+containsValue);

        //9. 遍历元素:方式2
        System.out.println("删除元素后=========================");
        for (Map.Entry<Integer, String> entry : treeMap.entrySet()) {
            Integer key = entry.getKey();
            String value = entry.getValue();
            // 处理键值对
            System.out.println("key: " + key + ", value: " + value);
        }

        //7. 获取键的集合:
        System.out.println("获取键的集合=========================");
        Set<Integer> keySet = treeMap.keySet();
        for (Integer i : keySet) {
            System.out.println(i);
        }

        //8. 获取值的集合
        System.out.println("获取键的集合=========================");
        Collection<String> values = treeMap.values();
        Iterator iterator = values.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

//运行结果
获取键为3对应的值为:d
删除元素前=========================
key: 1, value: b
key: 3, value: d
key: 4, value: c
key: 8, value: e
key: 16, value: a
key: 20, value: f
键‘8’是否存在:true ,值‘f’是否存在:false
删除元素后=========================
key: 1, value: b
key: 3, value: d
key: 4, value: c
key: 8, value: e
key: 16, value: a
获取键的集合=========================
1
3
4
8
16
获取键的集合=========================
b
d
c
e
a

5.3、Map集合的4种遍历方式

class test {
    public static void main(String[] args) {
        // 创建 HashMap 对象 Sites
        HashMap<Integer, String> Sites = new HashMap<Integer, String>();
        // 添加键值对
        Sites.put(1, "Google");
        Sites.put(2, "Runoob");
        Sites.put(3, "Taobao");
        Sites.put(4, "Zhihu");

        //遍历方式一:foreach增强循环遍历集合
        System.out.println("遍历方式一===============");
        for (Integer i : Sites.keySet()) {
            System.out.println("key: " + i + "; value: " + Sites.get(i));
        }

        //遍历方式二:for循环遍历集合
        System.out.println("遍历方式二===============");
        for (Map.Entry<Integer, String> entry : Sites.entrySet()) {
            Integer key = entry.getKey();
            String value = entry.getValue();
            // 处理键值对
            System.out.println("key: " + key + "; value: " + value);
        }

        //遍历方式三:迭代器遍历集合
        System.out.println("遍历方式三===============");
        Iterator<Map.Entry<Integer, String>> entries = Sites.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<Integer, String> entry = entries.next();
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println("key: " + key + "; value: " + value);
        }

        //遍历方式四:lambda两种方法遍历
        System.out.println("遍历方式四===============");
        Sites.forEach((key, value) -> {
            System.out.println("key: " + key + "; value: " + value);
        });
    }
}

//运行结果
遍历方式一===============
key: 1; value: Google
key: 2; value: Runoob
key: 3; value: Taobao
key: 4; value: Zhihu
遍历方式二===============
key: 1; value: Google
key: 2; value: Runoob
key: 3; value: Taobao
key: 4; value: Zhihu
遍历方式三===============
key: 1; value: Google
key: 2; value: Runoob
key: 3; value: Taobao
key: 4; value: Zhihu
遍历方式四===============
key: 1; value: Google
key: 2; value: Runoob
key: 3; value: Taobao
key: 4; value: Zhihu

六、HashTable

Hashtable是Java中的一个古老且已经过时的类,它实现了Map接口并继承自Dictionary类。Hashtable是线程安全的,但由于其同步机制的影响,性能可能会较低。在Java 1.2之后推荐使用更现代的HashMap替代Hashtable。

以下是Hashtable的一些基本特点和用法:

  1. 创建Hashtable对象:

    Hashtable<KeyType, ValueType> hashtable = new Hashtable<>();
    
  2. 添加元素:

    hashtable.put(key, value);
    
  3. 获取元素:

    ValueType value = hashtable.get(key);
    
  4. 删除元素:

    hashtable.remove(key);
    
  5. 判断键是否存在:

    boolean containsKey = hashtable.containsKey(key);
    
  6. 判断值是否存在:

    boolean containsValue = hashtable.containsValue(value);
    
  7. 获取键的集合:

    Enumeration<KeyType> keys = hashtable.keys();
    while (keys.hasMoreElements()) {
        KeyType key = keys.nextElement();
        // 处理key
    }
    
  8. 获取值的集合:

    Enumeration<ValueType> values = hashtable.elements();
    while (values.hasMoreElements()) {
        ValueType value = values.nextElement();
        // 处理value
    }
    
  9. 遍历元素:

    for (Map.Entry<KeyType, ValueType> entry : hashtable.entrySet()) {
        KeyType key = entry.getKey();
        ValueType value = entry.getValue();
        // 处理键值对
    }
    

需要注意的是,Hashtable不允许键或值为null,如果插入null键或值会抛出NullPointerException异常。如果需要使用可空键或值,可以考虑使用HashMap。

总之,尽量避免使用Hashtable,而是使用功能更强大且性能更好的HashMap或其他新的数据结构,如ConcurrentHashMap。

6.1、Hashtable 和 HashMap 的区别

Hashtable和HashMap都是Java中用于存储键值对的数据结构,它们有以下几个区别:

  1. 线程安全性:Hashtable是线程安全的,而HashMap是非线程安全的。在多线程环境中使用Hashtable时,不需要额外考虑同步问题;而在使用HashMap时,如果涉及到并发操作,需要额外的同步措施,例如使用ConcurrentHashMap。

  2. 键和值的null值:Hashtable不允许键或值为null,如果插入null键或值会抛出NullPointerException异常;而HashMap允许键和值为null,null键只能有一个,多个null值是可以的。

  3. 迭代器:Hashtable的枚举(Enumeration)和Iterator的使用和HashMap不同。Hashtable使用枚举来遍历元素,而HashMap使用Iterator来遍历元素。

  4. 性能:由于Hashtable是线程安全的,它在进行插入、删除和查找操作时需要考虑同步,在多线程环境下效率会较低。而HashMap在单线程环境下效率较高。

  5. 继承关系:Hashtable是基于Dictionary类实现的,而HashMap是基于AbstractMap类实现的。Dictionary是一个已过时的类,通常不推荐使用。

总的来说,如果你需要一个线程安全的映射表,可以使用Hashtable;如果不需要考虑线程安全性,并且希望有更好的性能,可以使用HashMap。

值得注意的是,自Java 1.2之后,推荐使用HashMap代替Hashtable。如果需要线程安全的映射表,可以考虑使用ConcurrentHashMap或使用Collections类的synchronizedMap方法将HashMap包装成线程安全的版本。

HashTable的5种遍历方式

class test {
    public static void main(String[] args) {
        Hashtable<String, String> hashtable = new Hashtable<String, String>();
        hashtable.put("1", "aa");
        hashtable.put("2", "bb");
        hashtable.put("3", "cc");


        //遍历方式一:使用 Enumeration 遍历 HashTable
        System.out.println("遍历方式一===============");
        Enumeration<String> keys = hashtable.keys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            String value = hashtable.get(key);
            System.out.println(key + "->" + value);
        }

        //遍历方式二:获取key集合的set视图根据key获取value
        System.out.println("遍历方式二===============");
        Set<String> set = hashtable.keySet();
        for (String key : set) {
            System.out.println(key + "->" + hashtable.get(key));
        }

        //遍历方式三:使用lambda表达式遍历hashtable
        System.out.println("遍历方式三===============");
        hashtable.forEach(
                (K, V) -> System.out.println("key : " + K + " value : " + V)
        );

        //遍历方式四:使用forEach循环遍历
        System.out.println("遍历方式四===============");
        for (Map.Entry<String, String> entry : hashtable.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "->" + value);
        }

        //遍历方式五:使用forEachRemaining方法遍历键值对
        System.out.println("遍历方式五===============");
        Iterator<Map.Entry<String, String>> iterator = hashtable.entrySet().iterator();
        iterator.forEachRemaining(entry -> {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "->" + value);
        });
    }
}

//运行结果
遍历方式一===============
3->cc
2->bb
1->aa
遍历方式二===============
3->cc
2->bb
1->aa
遍历方式三===============
key : 1 value : aa
key : 2 value : bb
key : 3 value : cc
遍历方式四===============
3->cc
2->bb
1->aa
遍历方式五===============
3->cc
2->bb
1->aa

你可能感兴趣的:(Java全套学习笔记,java,开发语言,后端)