Java集合框架 :接口:Collection、List 、Set、 Map;实现类:ArrayList、LinkedList、Vector、HashSet、TreeSet、HashMap、HashTable、TreeMap

java中集合类位于java.util包下,与下面四个接口有关Collection,List,Set,Map接口。

Collection接口

无索引,即无get方法

List接口

元素可重复、可以存放null值、有索引

Set接口

元素不可重复,无索引

ArrayList实现类

遍历速度快,插入数据效率低,线程不安全

Vector实现类

底层类似ArrayList、线程安全

LinkedList实现类

遍历速度慢,插入数据效率高,线程不安全

HashSet实现类

元素无顺序,可以存放null值,线程不安全,其有HashMap实现

TreeSet实现类

元素有顺序,不可存放null值,线程不安全,其有TreeMap实现,元素必须实现Comparable接口或Comparator接口

Map接口

具有key和value,其key一个Set,value为一个Collection集合

HashMap实现类

无顺序,线程不安全

HashTable实现类

无顺序,线程安全

TreeMap实现类

有顺序,线程不安全

一.Collection接口

Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。

Collection常用的方法:
boolean add(Object obj):向集合中加入Object对象,如果结合中已经存在该对象(注意这里的相同的对象是equals()返回的是true,既内容完全相同,而不是==)则直接返回false。

boolean contains(Object obj):集合中是否已经存在object对象,同时是指equals()方法比较对象返回true.

boolean remove(Object obj):从集合中移除Object对象。

void clear():清空集合。

int size():返回集合所包含的对象数目。

Object[] toArray():返回集合中全部对象的数组。

Object[] toArray(Object[] objs):把集合中的对象放入objs对象数组中,objs对象数组需要事先创建。

二.List接口

List集合代表一个元素有序,可重复的集合,集合中的每个元素都有其对应的顺序索引。

常用实现类:ArrayList  
LinkedList

遍历方式:for循环,Iterator

  1. 1.         
    List接口方法 

void add(int
index,Object e):将元素e添加到List集合中的index处; 
boolean addAll(int index,Collection c):将集合c所包含的所有元素都插入在List集合的index处; 
Object get(int index):返回集合index索引处的元素; 
int indexOf(Object o):返回对象o在List集合中第一次出现位置的索引; 
int lastIndexOf(object o):返回对象o在List集合中最后一次出现的位置索引; 
Object remove(int index):删除并返回index索引处的元素; 
Object set(int index,Object e):把集合index处的元素替换为e对象,返回以前在指定位置的元素; 
List subList(int fromIndex,int toIndex):返回从所有fromIndex(包括)到toIndex(不包括)处所有集合元素的子集合。 
ListIterator 
Iterator的子接口,专门用于操作List集合的输出; 
List自己还有一个listIterator()方法,该方法返回ListIterator对象,ListIterator继承了Iterator接口,提供了专门操作List的方法。在Iterator上额外增加的方法: 
支持双向输出: 
boolean hasPrevious():返回该迭代器关联集合是否还有上一个元素; 
Object previous():返回该迭代器的上一个元素;

2. List接口中常用类及区别

Vector:线程安全,但速度慢,已被ArrayList替代。 
ArrayList:线程不安全,查询速度快。 
LinkedList:链表结构,增删速度快。

Java的List接口有3个实现类,分别是ArrayList、LinkedList、Vector,他们用于存放多个元素,维护元素的次序,而且允许元素重复。

3个具体实现类的区别如下:

1).
ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除,允许空元素

2). Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。

3). LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,接口中没有定义的方法get,remove,insertList,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建 List时构造一个同步的List:
             List
list = Collections.synchronizedList(new LinkedList(...));

查看Java源代码,发现当数组的大小不够的时候,需要重新建立数组,然后将元素拷贝到新的数组内,ArrayList和Vector的扩展数组的大小不同。

关于ArrayList和Vector区别如下:

  • Array List在内存不够时默认是扩展50% + 1个,Vector是默认扩展1
  • Vector提供indexOf(obj,
    start)接口,ArrayList没有。
  • Vector属于线程安全级别的,但是大多数情况下不使用Vector,因为线程安全需要更大的系统开销。

3. ArrayList实现类

ArrayList 内部以数组的形式来保存集合中的元素,线程不安全;通常用for循环遍历。Vector线程安全,但Vector是个古老的类,存在很多缺点。

方法名

说明

boolean add(Object obj)

将元素添加到集合中

boolean add(int index,Object obj)

将元素obj插入到集合的index索引位置

Object get(int index)

返回集合中索引为index的元素

int indexOf(Object obj)

返回元素在集合中出现的索引

Object set(int index,Object obj)

将index索引位置的元素替换为obj元素

Object remove(int index)

删除并返回index索引位置的元素

boolean isEmpty ()

判断集合是否为空

boolean contains (Object obj)

判断集合中是否包含obj

示例:

  1. public class ArrayLsitDemo {
  2. /**
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. ArrayList<String> arr = new ArrayList<String>();
  7. //增
  8. arr.add("菠萝");
  9. arr.add("香蕉");
  10. arr.add("李子");
  11. print(arr);
  12. //删
  13. arr.remove(0);//根据索引删除,引用对象知识移除地址
  14. print(arr);
  15. //改
  16. arr.set(1, "橙子");
  17. print(arr);
  18. //查
  19. System.out.println(arr.get(0));
  20. }
  21. //遍历
  22. public static void print(ArrayList<String> arr){
  23. for(String str:arr){
  24. System.out.print(str + " ");
  25. }
  26. System.out.println();
  27. }
  28. }

4. LinkedList实现类

LinkedList可以根据索引来访问集合中的元素,此外还实现了Deque接口,所以也可以当成双端队列来使用,即可当“栈”(先进后出),也可以当作队(先进先出);内部是以线性表和链表实现的,保证输入的顺序。通常用Iterator遍历。

方法名

说明

void
addFirst(Object o)

将给定元素插入当前集合头部

void
addLast(Object o)

将给定元素插入当前集合尾部

Object
getFirst( )

获得当前集合的第一个元素

Object
getLast( )

获得当前集合的最后一个元素

Object
removeFirst( )

移除并返回当前集合的第一个元素

Object
removeLast( )

移除并返回当前集合的最后一个元素

示例:

  1. public class LinkedListDemo {
  2. /**
  3. * @param args
  4. */
  5. public static void main(String[] args) {
  6. LinkedList<String> list = new LinkedList<String>();
  7. list.add("哈哈");
  8. list.add("呵呵");
  9. list.add("嘿嘿");
  10. print(list);
  11. list.addFirst("嘻嘻");//链表可以在头或尾插入
  12. print(list);
  13. //将元素加入到对头
  14. list.offerFirst("来来");
  15. //将元素加入到队尾
  16. list.offerLast("去去");
  17. print(list);
  18. //访问并不删除栈顶
  19. System.out.println("访问并不删除栈顶----" +list.peekFirst());
  20. print(list);
  21. //访问并删除栈顶
  22. System.out.println("访问并删除栈顶----" + list.poll());
  23. print(list);
  24. }
  25. public static void print(List list){
  26. Iterator iterator = list.iterator();
  27. while(iterator.hasNext()){
  28. System.out.print(iterator.next() + " ");
  29. .         }
  30. System.out.println();
  31. .     }
  32. }

三.Set接口

List集合代表一个元素不可重复的集合。操作数据的方法与List类似,Set接口不存在get()方法

常用实现类:HashSet(无序)  TreeSet(有序)

遍历方式:for循环,Iterator

  1. 1.         
    Set接口方法 

添加元素

boolean add(E e)   如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。

boolean addAll(Collection<? extends E> c) 如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中(可选操作)。

遍历Set

Iterator<E>
iterator()  返回在此 set 中的元素上进行迭代的迭代器。

是否为空

boolean
isEmpty() 如果 set 不包含元素,则返回 true。

元素个数

int size()  返回 set 中的元素数(其容量)。

清除元素

void clear()  移除此 set 中的所有元素(可选操作)。

boolean remove(Object o) 如果 set 中存在指定的元素,则将其移除(可选操作)。

boolean removeAll(Collection<?> c)  移除 set 中那些包含在指定 collection 中的元素(可选操作)。

是否包含元素或集合

boolean contains(Object o)  如果 set 包含指定的元素,则返回 true。

boolean containsAll(Collection<?>
c)  如果此 set 包含指定 collection 的所有元素,则返回 true。

其他

boolean equals(Object o) 比较指定对象与此 set 的相等性。

int hashCode() 返回 set 的哈希码值。

Object[]
toArray()  返回一个包含 set 中所有元素的数组。

<T> T[]  toArray(T[] a) 返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。

  1. 2.         
    HashSet实现类 

此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。

注意,此实现不是同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这通常是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在创建时完成这一操作,以防止对该 set 进行意外的不同步访问:

Set s = Collections.synchronizedSet(new
HashSet(...));

  1. 3.         
    TreeSet实现类 

基于 TreeMapNavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

注意,如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅 Comparable 或 Comparator。)这是因为 Set 接口是按照 equals 操作定义的,但 TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。即使 set 的顺序与 equals 不一致,其行为也是 定义良好的;它只是违背了 Set 接口的常规协定。

注意,此实现不是同步的。如果多个线程同时访问一个 TreeSet,而其中至少一个线程修改了该 set,那么它必须 外部同步。这一般是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSortedSet 方法来“包装”该 set。此操作最好在创建时进行,以防止对 set 的意外非同步访问:

SortedSet s =
Collections.synchronizedSortedSet(new TreeSet(...));

TreeSet原理

/*
 * TreeSet存储对象的时候, 可以排序, 但是需要指定排序的算法
 * 
 * Integer能排序(有默认顺序), String能排序(有默认顺序), 自定义的类存储的时候出现异常(没有顺序)
 * 
 * 如果想把自定义类的对象存入TreeSet进行排序, 那么必须实现Comparable接口
 *   在类上implement Comparable
 *   重写compareTo()方法
 *   在方法内定义比较算法, 根据大小关系, 返回正数负数或零
 *   在使用TreeSet存储对象的时候, add()方法内部就会自动调用compareTo()方法进行比较, 根据比较结果使用二叉树形式进行存储
 */

四.Map接口

Map接口储存一组成对的键-值对象,提供key(键)到value(值)的映射,Map中的key不要求有序,不允许重复。value同样不要求有序,但可以重复。最常见的Map实现类是HashMap,他的储存方式是哈希表,优点是查询指定元素效率高。

常用实现类:HashMap(无序)  TreeMap(有序)、HashTable(过时)

遍历方式:for循环,Iterator

  1. 1.         
    Map接口方法 

Map 接口的常用方法如下所示:

No.

方法

类型

描述

1

V put(K key,V value)

普通

增加内容

2

V get(Object key)

普通

取得设置的内容,根据key取得

3

boolean containsKey(Object key)

普通

查找指定的key 是否存在

4

boolean containsValue(Object value)

普通

查找指定的value 是否存在

5

boolean isEmpty()

普通

判断集合是否为空

6

Set<K> keySet()

普通

将全部的key变为Set 集合

7

Collection<V> values()

普通

将全部的value 变为Collection集合

8

V remove(Object key)

普通

根据key 删除内容

9

void putAll(Map<? extends K,? extends V>m)

普通

增加一组数据

  1. 2.         
    HashMap实现类 

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

注意,此实现不是同步的。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须 保持外部同步。(结构上的修改是指添加或删除一个或多个映射关系的任何操作;仅改变与实例已经包含的键关联的值不是结构上的修改。)这一般通过对自然封装该映射的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的非同步访问,如下所示:

Map m =
Collections.synchronizedMap(new HashMap(...));

  1. 3.         
    TreeMap实现类 

基于红黑树(Red-Black
tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

注意,此实现不是同步的。如果多个线程同时访问一个映射,并且其中至少一个线程从结构上修改了该映射,则其必须 外部同步。(结构上的修改是指添加或删除一个或多个映射关系的操作;仅改变与现有键关联的值不是结构上的修改。)这一般是通过对自然封装该映射的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSortedMap 方法来“包装”该映射。最好在创建时完成这一操作,以防止对映射进行意外的不同步访问,如下所示:

SortedMap m = Collections.synchronizedSortedMap(new
TreeMap(...));

  1. 4.         
    HashMapHashTable区别

Hashtable 实际上与Vector 的产生时代是一样,也属于最早的集合操作类。之后只是扩展了其应用实现了Map 接口而已

HashTable类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。

为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。

No

区别点

HashMap

Hashtable

1

推出时间

是在JDK1.2之后推出的,属于新的类

是在JDK1.0时推出的,属于旧的操作类

2

操作

采用异步的处理操作

采用同步的处理操作

3

性能

性能高

性能相对较低

4

安全

非线程安全的操作

线程安全

五.Collections

Java中给我们提供了一个工具类Collections来方便我们操作集合,在该类中的全部方法均为static静态方法,可以直接通过类名调用。其中比较常用的方法有以下方法:

void sort(List
list,Comparator com)-- >如果我想将一个List数组进行排序,需要将数组中元素取出再放入一个TreeSet集合然后再传入一个比较器,而用这个方法直接传入一个比较器就可以了

void max(List
list,Comparator com)-- >根据比较器取出最大值

int
binarySearch(List list,Object key)-- >找出List集合元素key并返回搜索键的索引。注意执行该方法时必须要对集合进行sort操作,否则结果是不明确的,或者在参数中再传入一个比较器。如果没有该元素,则返回(-(插入点)-1)。

void fill(List
list,Object obj)-- >将list集合中所有元素换为obj

void replaceAll(List
list,ObjectoldValue,Object newValue)-- >将集合中所有为oldValued的元素换成newValue元素。

void
reverse(List list)-- >将集合翻转

Comparator
reverseOrder()-- >返回一个比较器,可以讲集合内元素顺序倒转。

CollectionsynchronizedCollection(Collection
collection) -- >通过传入集合获得一个同步的集合

List synchronizedList(List
list)

Set
synchronizedSet(Set set)

Map
synchronizedMap(Map map)

void swap(List
list,int index1,int index2)-->将集合list中角标为index1和index2的元素互换位置

六.泛型

泛型是java在jdk1.5之后才出现的。因为操作集合的时候每次都要判断元素类型,会出现ClassCastException。所以引入了泛型机制,使元素类型在编译的时候就做了限定。例如定义一个Collection <String> c=new Collection<String> ();那么这个Collection集合中就只能存入String类型的对象。

参数化类型不考虑类型参数的继承关系,比如Vector<String>v
= new Vector<Object>()或者Vector<Object> v = new Vector<String>();都是错误的。如果想达到这个效果可以用通配符来做到。如Vector<?extends Object> v=new Vector<String>()。

使用?通配符可以引用其他各种参数化类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。如我们定义一个打印参数化集合的方法。

public void printCollection(Collection<?>
collection )

{

for(Object obj:collection)

System.out.println(obj);

}

collection.size();//正确,因为此方法与类型参数没有关系

collection.add(“abc”);//错误,因为collection不能确定自己匹配的参数是String

通配符的上限是?extends T;通配符的下限是? super T。

泛型是提供给Javac编译器使用的。可以限定集合中输入的类型,让编译器挡住原始程序的非法输入,编译器编译带类型说明的集合时会去掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样,由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

void sort(List
list,Comparator com)-- >如果我想将一个List数组进行排序,需要将数组中元素取出再放入一个TreeSet集合然后再传入一个比较器,而用这个方法直接传入一个比较器就可以了

void max(List
list,Comparator com)-- >根据比较器取出最大值

需要注意的几点是泛型的实际参数只能是引用类型不可以是基本类型,泛型定义在类上时。类中的静态成员不具备该类型参数

集合框架基础知识-----java基础知识的更多相关文章

  1. 集合3--毕向东java基础教程视频学习笔记

    Day 15 集合框架01 TreeSet02 TreeSet存储自定义对象03 二叉树04 实现Comparator方式排序05 TreeSet练习06 泛型概述07 泛型使用08 泛型类09 泛型 ...

  2. 集合1--毕向东java基础教程视频学习笔记

    Day14 集合框架01 体系概述02 共性方法03 迭代器04 List集合共性方法05 ListIterator06 List集合具体对象特点07 Vector中的枚举 01 体系概述 集合类为什 ...

  3. 【JAVA集合框架一 】java集合框架官方介绍 Collections Framework Overview 集合框架总览 翻译 javase8 集合官方文档中文版

    原文链接: https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html 原文内容也一并附加在本文最 ...

  4. 【Java 基础】Java 基础索引

    Java 基础 注解 [注解]深入理解Java注解类型(@Annotation) [注解]Java注解(1)-基础 [注解]Java注解(2)-运行时框架 [注解]Java注解(3)-源码级框架

  5. 集合框架(JCF/Java Collection Framework)

    集合的特点:1.数据的类型可以不同2.集合长度可变3.空间不固定集合也是对象,用于检索,存储以及传输对象集合框架的组成Collection接口和Map接口 Collection是Set接口和List接 ...

  6. Java集合框架介绍。Java Collection Frameworks = JCF

    Java集合框架 = Java Collection Frameworks  = JCF . 为了方便理解,我画了一张思维脑图.

  7. Java入门系列(七)Java 集合框架(JCF, Java Collections Framework)

    Java 集合概述 List.Set.Map可以看做集合的三大类 java集合就像一个容器,可以将多个对象的引用丢进该容器中. Collection和Map是java集合的根接口. List List ...

  8. 集合2--毕向东java基础教程视频学习笔记

    Day14 08 LinkedList09 LinkedList练习10 ArrayList练习11 ArrayList练习2 12 HashSet13 HashSet存储自定义对象14 HashSe ...

  9. 从c#基础到java基础的学习的感悟

    从进入培训公司到现在已经有三周多了,我想我和绝大多数人一样,能考虑进入培训学校,肯定是心理做好了准备的,那就是只有一个目的学好这门技术,从之前的开班典礼来看,从每个同学的自我介绍,我们这的大部分人来这 ...

随机推荐

  1. 【LG3768】简单的数学题

    [LG3768]简单的数学题 题面 求 \[ (\sum_{i=1}^n\sum_{j=1}^nij\text{gcd}(i,j))\text{mod}p \] 其中\(n\leq 10^{10},5 ...

  2. P3302 [SDOI2013]森林

    树上第k小是裸题,然后连边操作显然只能用启发式合并 连边之后重构小的部分,重构一遍主席树和倍增数组,水的一批(逃 #include<bits/stdc++.h> #define il in ...

  3. centos 6.5 搭建开源堡垒机 Teleport 遇到的问题解决

    几款开源的堡垒机 下面进行 teleport 的安装: https://docs.tp4a.com/install/#11 异常1:libc.so.6: version `GLIBC_2.14' no ...

  4. servelt filter listener 的生命周期

    1. servlet    当第一次请求一个servlet资源时,servlet容器创建这个servlet实例,并调用他的 init(ServletConfig config)做一些初始化的工作,然后 ...

  5. TensorFlow训练MNIST数据集(1) —— softmax 单层神经网络

    1.MNIST数据集简介 首先通过下面两行代码获取到TensorFlow内置的MNIST数据集: from tensorflow.examples.tutorials.mnist import inp ...

  6. 前端常见算法面试题之 - 二维数组中的查找[JavaScript解法]

    --------------------- 作者:吴潇雄 来源:CSDN 原文:https://blog.csdn.net/weixin_43439741/article/details/835118 ...

  7. EOS开发基础之四:使用cleos命令行客户端操作EOS——智能合约之eosio.bios和eosio.token

    现实世界中的合约,简单地说,是一个参与活动的所有人都需要遵循的协议.合约可以是正式的法律合同(例如,金融交易),或者是简单的游戏规则.典型的活动可以是诸如资金转移(在金融合约的情况下)或游戏动作(在游 ...

  8. PAT甲题题解-1126. Eulerian Path (25)-欧拉回路+并查集判断图的连通性

    题目已经告诉如何判断欧拉回路了,剩下的有一点要注意,可能图本身并不连通. 所以这里用并查集来判断图的联通性. #include <iostream> #include <cstdio ...

  9. 词频统计 SPEC 20160911

    本文档随时可能修改,并且没有另行通知. 请确保每一次在开始修改你的代码前,读标题中的日期,如果晚于你上次阅读, 请重读一次. 老五在寝室吹牛他熟读过<鲁滨逊漂流记>,在女生面前吹牛热爱&l ...

  10. Linux内核的启动过程分析

    秦鼎涛 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验目的及要求: 使用gdb跟踪调试内核从s ...