您的位置:首页 > 职场人生

黑马程序员--集合框架

2015-07-28 23:21 531 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

注:视频来源,毕向东老师的 JAVA 基础视频。

集合框架

概论:

集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。

接口:即表示集合的抽象数据类型。接口提供了让我们对集合中所表示的内容进行单独操作的可能。

实现:也就是集合框架中接口的具体实现。实际它们就是那些可复用的数据结构。

算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算的方法,例如查找、排序等。

集合框架的构成图解:



第一部分:Collection 和 Iterator

List :元素是有序的,元素可以重复

Set :元素是无序的,元素不可以重复。

|–List:元素是有序的,元素可以重复。因为该集合体系由索引。

|–ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,增删稍慢。线程不同步,效率高

|–LinkedList:底层使用的是链表数据结构。特点:增删速度快,查询稍慢。

|–Vector:底层是数组数据结构。线程同步。效率低,被ArrayList替代了。

|–Set :元素是无序的,元素不可以重复。

|–HashSet:底层数据结构是 ” 哈希表 “。

|–TreeSet:可以对 Set 集合中的元素进行判断。

集合框架的概念:

为什么会出现这么多的容器呢?因为每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构。

一、ArrayList 和 迭代器Iterator

1.1 List 的重点部分:

List 集合特有的迭代器ListIterator 是 Iterator 的子接口。在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生修改异常。所以在迭代时,只能用迭代器的方法操作元素, 可是 Iterator 方法是有限的。只能对元素进行判断,取出,删除操作。如果想要其它的操作如添加,修改等,就需要使用其子接口 ListIterator

1.2 List:特有方法,凡是可以操作脚标的方法都是该体系的特有的方法。

1)增

add(index,element);

addAll(index,Collection)

2)删

remove(index);

3)改

set(index,elemnts)

4)查

get(index)

subList(from,to)

listIterator()

1.3 ArrayList 数组的默认长度:构造一个初始容量为10的数组,若超过初始容量,则新增一个容量为5的数组。

1、集合中的 add 方法的参数类型是 Object 。以便于接受任意类型对象。

2、集合中存储的都是对象的引用(地址)。

1.4 什么是迭代器 Iterator?

迭代器是一种设计模式,通俗的讲就是:遍历集合,集合的取出元素的方式。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

1、使用next()获得序列中的下一个元素。

2、使用hasNext()检查序列中是否还有元素。

3、使用remove()将迭代器新返回的元素删除。

1.5 ArrayList 和 Iterator 的 示例:

package fuxi;

import java.awt.List;
import java.util.ArrayList;

/**
*
*@author XiaLei
*/
public class Day14Test1 {

public static void main(String[] args) {

ArrayList<String> al = new ArrayList<String>();

ArrayList<String> alt = new ArrayList<String>();
alt.add("lei:");
al.add("abuihba");//添加元素
System.out.println(al);
//      al.add(1, "t");
//      al.add(2, "l");//指定位置添加元素
//      System.out.println(al);
alt.addAll(al);//添加集合
System.out.println(alt);
//      alt.remove(1);//删除
//      System.out.println(alt);
alt.set(1, "xia");//修改
System.out.println(alt);
System.out.println(alt.get(0));//获取
alt.add("hahah");
alt.add("hehehe");
//      System.out.println(alt.subList(1, 3));//获取指定位置元素
//      for (Iterator<String> it = alt.iterator();it.hasNext();){
//          System.out.println(it.next());//创建迭代器,取 出元素。
//      }
System.out.println(alt.indexOf("hahah"));
System.out.println(alt.lastIndexOf("hahah"));
}

}


1.6 ListIterator示例:

package fuxi;

import java.util.ArrayList;
import java.util.ListIterator;

/**
* ListIterator是List集合特有迭代器。其在遍历过程中课进行增删改查操作。还存在hasPrevious()特有遍历方法。
*@author XiaLei
*/
public class Day14Test2 {

public static void main(String[] args) {

ArrayList<String> al = new ArrayList<String>();
al.add("java01");
al.add("java02");
al.add("java04");
al.add(2,"java03");
ListIterator<String> li = al.listIterator();
while (li.hasNext()){
Object obj = li.next();
if(obj.equals("java02")){
//              li.set("java002");//修改操作
//              li.remove();//删除操作
li.add("java002");//如果写al.add("java002")则会发生并发异常。因为创建迭代器的时候,集合里的元素并没有"java002"。
}
System.out.println(obj);//这里改变的是集合对元素“Java02”的指向,obj任然指向“java02”。
}
System.out.println(al);
//特有向前遍历方式
while(li.hasPrevious()){
Object obj = li.previous();
if(obj.equals("java002")){
//              li.remove();
li.set("hehe");
}
}
System.out.println(al);
}

}


1.7 ArrayList练习:

package fuxi;

import java.util.ArrayList;
import java.util.ListIterator;

/**
* 题目:判断含有人(具有姓名,年龄属性)的ArrayList是否有重复元素。
* 思路:对人进行描述,定义容器,取出。
* 总结:List集合判断元素是否相同,依据的是元素的equals方法。
*@author XiaLei
*/
public class Day14Test7 {

public static void main(String[] args) {

Person p1 = new Person("zhan01",2);
Person p2 = new Person("zhan02",2);
Person p3 = new Person("zhan01",3);
Person p4 = new Person("zhan01",2);
ArrayList<Person> al = new ArrayList<Person>();
al.add(p1);
al.add(p2);
al.add(p3);
al.add(p4);
System.out.println(beDefferent(al));

}
public static ArrayList<Person> beDefferent(ArrayList<Person> al){
ArrayList<Person> alt = new ArrayList<Person>();
ListIterator<Person> li = al.listIterator();
while(li.hasNext()){//迭代循环中,next一次就要判断一次hasNext。
Person p = li.next();
if(!alt.contains(p)){//contains底层调用equals方法。另外remove方法也是调用equals的。
alt.add(p);
}
}
return alt;
}
}
class Person{
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public boolean equals(Object obj){
//复写equals方法。
if(!(obj instanceof Person))
return false;
Person p =(Person)obj;
return this.name.equals(p.name) &&this.age == p.age;
}
public String toString(){
return "name="+this.name+"  age="+this.age;
}
}


二、LinkedList

2.1 理解:底层使用的是链表数据结构。

特点:增删速度快,查询稍慢。

2.2 LinkedList 特有的方法:

1、addFirst();

2、addLast();

3、getFirst();

4、getLast();

获取元素,但是不删除元素。如果集合中没有元素,会出NoSuchElementException

5、removeFirst();

6、removeLast();

获取元素,但是元素被删除。如果果集合中没有元素,会出现NoSuchElementException

2.3 JDK 1.6 出现了替代方法

1、offerFirst()

2、offerLast()

3、peekFirst()

4、peekLast()

获取元素,但不删除元素,如果集合中没有元素,返回 null

5、pollFirst()

6、poolLast()

获取元素,但是元素被删除,如果集合中没有元素,返回 null

2.4 LinkedList示例:

package fuxi;

import java.util.LinkedList;

/**
* LinkedList的特有方法
*@author XiaLei
*/
public class Day14Test4 {

public static void main(String[] args) {
//JDK1.6出现的替代方法分别为 offer..peek..poll..
LinkedList<String> l = new LinkedList<String>();
l.addLast("java03");
l.offerLast("java04");
l.addFirst("java02");
l.offerFirst("java01");
System.out.println(l);
System.out.println(l.getFirst());
System.out.println(l.peekLast());
System.out.println(l.removeFirst());
System.out.println(l.pollFirst());
l.clear();//清空元素
//      System.out.println(l.removeLast());//没有元素,出现java.util.NoSuchElementException异常
System.out.println(l.pollLast());//返回null
}

}


2.5 利用LinkedList 封装堆栈和队列数据结构:

package fuxi;

import java.util.LinkedList;

/**
* 利用LinkedList 封装堆栈和队列数据结构。
* 队列:先进先出,如水管。
* 堆栈:先进后出,如杯子。
* 这里再次体现了封装的思想,事实上在以后的开发中,我们经常需要创建属于自己项目的功能。
*@author XiaLei
*/
public class Day14Test5 {

public static void main(String[] args) {

DuiZhan dz = new DuiZhan();
dz.myAdd("java01");
dz.myAdd("java02");
dz.myAdd("java03");
dz.myAdd("java04");
while(!dz.isNull()){
System.out.println(dz.myGet());
}
}

}
class DuiZhan{
private LinkedList<Object> list;
DuiZhan(){
list = new LinkedList<Object>();
}
public void myAdd(Object obj){
list.addFirst(obj);//这里只要改成addLast就可以变成队列结构。
}
public Object myGet(){
return list.removeFirst();
}
public boolean isNull(){
return list.isEmpty();
}
}


三、Vector

3.1 枚举:Enumeration就是 Vector 特有的取出方式。

3.2 发现枚举和迭代器很相向。其实枚举和迭代其实是一样的。因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。

3.3 示例:

package fuxi;

import java.util.Enumeration;
import java.util.Vector;

/**
* 枚举是vector特有的取出方式,跟迭代器功能重复,由于书写不便,被取代。
*@author XiaLei
*/
public class Day14Test3 {

public static void main(String[] args) {

Vector<String> v = new Vector<String>();
v.add("java01");
v.add("java02");
v.add("java03");
v.add("java04");
Enumeration<String> en = v.elements();
while(en.hasMoreElements()){
System.out.println(en.nextElement());
}
}

}


Set 分为 HashSet 和 TreeSet 两部分。

四、Set 中的 HashSet

1) HashSet:底层数据结构是 ” 哈希表 “。哈希值如果一样,就对比是不是同一个对象。

2) HashSet 是如何保持元素的唯一性呢?

是通过元素的两个方法 hashCode 和 equals 来完成。

如果元素的 HashCode 值相同,才会判断 equals 是否为 true

如果元素的 HashCode 的值不同,就不会调用 equals 。

注意,对于判断元素是否存在,以及删除等操作。依赖的方法是元素的 hashCode 和 equals 方法。

五、Set 中的 TreeSet

1) TreeSet:可以对 Set 集合中的元素进行判断。

2) 注意:必须要让你的对象具备比较性,他才能进行比较排序,所以实现comparable这个比较接口就符合treeset要求了。这种比较性,称为底层数据结构是二叉树。它保证元素唯一性的依据:compareTo 方法 return 0;

3) TreeSet 排序的第一种方式:

让元素自身具有比较性。元素需要实现 Comparable 接口。覆盖compareTo 方法。这种方式也成为元素的自然顺序,或者叫做默认顺序。

4) TreeSet 的第二种排序方式:

当元素自身比具备比较性,或具备的比较性不是所需的。这时,就需要让集合自身具备比较性。

5) 在集合一初始化时就有了比较方式。

6) 当元素自身比具备比较性,或具备的比较性不是所需的。这时,就需要让容器自身具备比较性。定义了比较器,将比较器对象作为参数传递给 TreeSet 集合的构造函数。

当两种排序都存在时,以比较器为主。

定义一个类,实现 Comparator 接口,覆盖 compare 方法。

实现Comparable和 Comparator 的实例:

package fuxi1;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**
* 需求:利用TreeSet给自定义对象排序。
* 思路:TreeSet底层数据结构是二叉树,其保证元素唯一性的依据:compareTo方法return 0;
* TreeSet排序的方法有两个:1.元素需要实现comparable接口,覆盖compareTo方法。让元素自身具备比较性,也称默认顺序。
* 2.当元素自身不具备比较性或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性,步骤是:实现Comparator接口,覆盖compare方法。
* 注意:当两种排序都存在是,以比较器的为主。
*@author XiaLei
*/
public class Day15Test1 {

public static void main(String[] args) {

TreeSet<Student> ts = new TreeSet<Student>(new MyCom());
ts.add(new Student("hello07",4));
ts.add(new Student("hello05",4));
ts.add(new Student("hello04",66));
ts.add(new Student("hello01",45));
System.out.println(ts);
Iterator<Student> it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}

}
class Student implements Comparable<Student>{//让学生对象自身具备比较性
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int compareTo(Student s){

if (this.age>s.age)
return 1;
if (this.age==s.age)
return this.name.compareTo(s.name);//主要条件相同比较次要条件。
else
return -1;
}
public String toString(){
return "name="+this.name+"  age="+this.age;
}
}
//自定义比较器
class MyCom implements Comparator<Student>{

public int compare(Student s1,Student s2){
int num = s1.getName().compareTo(s2.getName());
if(num == 0){
return (new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())));//主要条件相同比较次要条件。
}
return num;
}
}


7) TreeSet 练习:按照字符串长度排序

package fuxi1;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**
* 练习:利用TreeSet集合对字符串长度进行排序。
* 思路:字符串本身具有比较性,考虑自定义比较器的方法比较简单。
*@author XiaLei
*/
public class Day15Test2 {

public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<String>(new MyComparator());
ts.add("abd");
ts.add("afsdf");
ts.add("af");
ts.add("abc");
for(Iterator<String> it = ts.iterator(); it.hasNext();){
System.out.println(it.next());
}
}

}
class MyComparator implements Comparator<String>{
public int compare(String str1,String str2){
int num = str1.length()-str2.length();
if (num==0)
return str1.compareTo(str2);//如果长度相等按照字符串自然顺序排位。
return num;
}
}


第二部分:Map

一、 Map 基本内容

1)Map 集合的存储方式: 该集合存储键值对,成对性的往里存,而且要保证数据的唯一性。其实,Map 和 Set 很像,是因为 Set 的底层数据结构就是使用了 Map 集合。

注意了:当发现有存在映射关系时,可以选择 map 集合。因为 map 集合中存放的就是映射关系。

2)Map 集合中的三个子类:

|–HashTable:底层是哈希表数据结构,不可以存入 null 键和 null 值。该集合时线程同步的。 效率低。

|–HashMap: 底层是哈希表数据结构,允许使用 null 键和 null 值。该集合时不同步的。 效率高。

|–TreeMap: 底层是二叉树数据结构,线程不同步。可以用于给 Map 集合中的键进行排序。

3) Map 集合的基本操作:

1、添加。

put(K,V);

putAll(Map

package fuxi1;

import java.util.HashMap;
import java.util.Map;

/**
* Map集合的共性方法练习。
*@author XiaLei
*/
public class Day16Test1 {

public static void main(String[] args) {
Map<Integer,String> m = new HashMap<Integer,String>();
m.put(1, "java01");
System.out.println(m.put(1, "java02"));//如果添加相同键时,新的value会替换旧的,并返回旧的value
m.put(2, "java05");
m.put(3, "java06");
m.put(4, "java07");
m.put(null, null);//特殊的:HashMap可以存入null键和值,HashTable则不可以。
System.out.println(m);
System.out.println(m.remove(4));//移除元素并返回对应的value
System.out.println(m.containsKey(1));//判断是否有键
System.out.println(m.containsValue("java07"));//判断是否有值
System.out.println(m.get(3));//获取对应值
System.out.println(m.size());//判断集合大小
System.out.println(m.values());//获取所有value的collection
m.clear();//清空集合
System.out.println(m.isEmpty());//判断是否为空
}

}


二、Map 集合中的两种取出方式

1、Set < key> keySet:将 map 中所有的值存入到 Set 集合。因为 Set 具备迭代器。所以可以迭代方式取出所有的键,在根据 get 方法,获取每一个键的值。

Demo:

package fuxi1;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
* Map集合有两种取出方式:keySet()和entrySet()
*@author XiaLei
*/
public class Day16Test2 {

public static void main(String[] args) {

Map<Integer,String> m = new HashMap<Integer,String>();
m.put(1, "java01");
m.put(2, "java05");
m.put(3, "java06");
m.put(4, "java07");
//keySet()返回的是Set集合,该Set集合存储着Map集合的所有键。
Set<Integer> s = m.keySet();
//利用迭代器,取出这些键。
Iterator<Integer> it = s.iterator();
while(it.hasNext()){
Integer i = it.next();
String value = m.get(i);//利用get()方法获取对应键值。
System.out.println(i+"="+value);
}
}

}


2、Set< Map.Entry< k,v>> entrySet:将 map 集合中的映射关系存入到 Set 集合中。而这个关系的数据类型就是:Map.Entry

Map.Entry:其实 Entry 也是一个接口,它是 Map 接口中的一个内部接口。

Demo:

package fuxi1;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
* entrySet()是将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是Map.Entry。
* 事实上,Entry就是Map接口中的一个内部静态接口。
*@author XiaLei
*/
public class Day16Test3 {

public static void main(String[] args) {

Map<Integer,String> m = new HashMap<Integer,String>();
m.put(1, "java01");
m.put(2, "java05");
m.put(3, "java06");
m.put(4, "java07");
Set<Map.Entry<Integer,String>> s = m.entrySet();
Iterator<Map.Entry<Integer,String>> it = s.iterator();
while(it.hasNext()){
Map.Entry<Integer,String> me= it.next();//返回的是映射关系,这也是一种数据类型,即Map.Entry;
Integer i = me.getKey();//利用Map.Entry特有的getKey()和getValue()方法获取键值。
String st = me.getValue();
System.out.println(i+"="+st);

}
}

}


3、Map 的练习

1) HashMap 练习:

package fuxi1;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
* 题目:每一个学生都有对应的归属地,学生Student,归属地String,学生有属性姓名和年龄,属性相同视为同一个学生。保证学生的唯一性。
* 思路:1.先描述学生,因为要确保唯一性,所以要用HashMap集合,学生类中要覆盖hashCode()和equals()方法。
* 2.定义Map集合,将学生和归属地作为键值存入
* 3.获取集合中的元素
*@author XiaLei
*/
public class Day16Test4 {

public static void main(String[] args) {
Students st1 = new Students("java01",5);
Students st2 = new Students("java02",2);
Students st3 = new Students("java04",4);
Students st4 = new Students("java01",5);
String addr1 = st1.diZhi("BeiJin01");
String addr2 = st1.diZhi("BeiJin02");
String addr3 = st1.diZhi("BeiJin03");
String addr4 = st1.diZhi("BeiJin04");

Map<Students,String> m = new HashMap<Students,String>();
m.put(st1,addr1);
m.put(st2,addr2);
m.put(st3,addr3);
m.put(st4,addr4);
//entrySet取出方式:
Set<Map.Entry<Students,String>> s = m.entrySet();
Iterator<Map.Entry<Students,String>> it = s.iterator();
while(it.hasNext()){
Map.Entry<Students, String> me = it.next();
Students key = me.getKey();
String value = me.getValue();
System.out.println(key+"="+value);
}
//keySet取出方式:
Set<Students> st = m.keySet();
for(Iterator<Students> its =st.iterator();its.hasNext();){
Students key1 = its.next();
String value1 = m.get(key1);
System.out.println(key1+"="+value1);
}
}

}
class Students implements Comparable<Students>{//实现Comparable接口,让Students类具有自然顺序。
private String name;
private int age;
public Students(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String diZhi(String addr){
return addr;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
//重写compareTo方法
public int compareTo(Students s){
int num = this.age-s.age;
if(num==0){
return this.name.compareTo(s.name);
}
return num;
}
//复写hashCode方法
public int hashCode(){
return name.hashCode()+age*39;
}
//复写equals方法
public boolean equals(Object obj){
if (!(obj instanceof Students))
throw new RuntimeException("类型不匹配");//注意异常的使用,这里如果return false;没有意义 所以要抛出一个运行时异常。
Students st = (Students)obj;
return this.name.equals(st.name) && this.age==st.age;
}
public String toString(){
return "name:"+name+"...age:"+age;
}
}


2) TreeMap 练习:

package fuxi1;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
* 题目:"jakldfjasldfj"获取一个字符串中每个字母出现的次数。
* 希望打印的结果为:a(2)d(1)...
* 思路:1、将字符串转成字符数组。因为要对每一个字母进行操作。
* 2、定义一个 map 集合,因为打印结果的字母有顺序,所以使用 TreeMap 集合。
* 3、遍历字符数组,将每一个字母作为键去查 map 集合。如果返回 null ,将该字母和 1 存入到 Map 集合中。
*  如果返回不是 null ,说明该字母在 map 集合内已经存在。并有对应的次数。
* 那么就获取该次数并进行自增。然后将该字母和自增后的次数,存入到 map 集合中。覆盖掉原集合键所对应的值。
* 4、将 map 集合中的数据变成指定的字符串形式返回。
*@author XiaLei
*/
public class Day16Test6 {

public static void main(String[] args) {

String str = "jakldfj66asldfj";
char[] arr = str.toCharArray();//将字符串变成字符数组。
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
int count = 0;
for(int x = 0;x<arr.length;x++){
char ch = arr[x];
String reg = "[a-zA-Z]";//利用正则表达式判断元素是否为字母。
if(!(String.valueOf(ch).matches(reg)))
continue;

if(tm.containsKey(ch)){
Integer value = tm.get(ch);
count = value;//如果有相同的键(字母)则将对应的值赋给count。
}
count++;
tm.put(ch,count);
count = 0;//将计数器清零,这一点很容易出错,应牢记。
}
Set<Map.Entry<Character,Integer>> s = tm.entrySet();
for(Iterator<Map.Entry<Character,Integer>> it = s.iterator(); it.hasNext();){
Map.Entry<Character,Integer> me = it.next();
Character key = me.getKey();
Integer value = me.getValue();
System.out.print(key+"("+value+")");
}
}
}


3) Map 拓展练习:

在很多项目中,应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。

package fuxi1;

import java.util.HashMap;
import java.util.Iterator;

/**
* Map集合扩展知识:
* Map集合中可以嵌套Map。
*@author XiaLei
*/
public class Day16Test7 {

public static void main(String[] args) {

HashMap<String,HashMap<Integer,String>> school = new HashMap<String,HashMap<Integer,String>>();
HashMap<Integer,String> room_1 = new HashMap<Integer,String>();
HashMap<Integer,String> room_2 = new HashMap<Integer,String>();//学校里面有两个班级,每个班级里面有学生。
school.put("room_1", room_1);
school.put("room_2", room_2);

room_1.put(01, "zhansan");
room_1.put(02, "lisi");
room_2.put(01, "wangwu");
room_2.put(02, "zhaoliu");

Iterator<String> it = school.keySet().iterator();//遍历学校集合的键
while(it.hasNext()){
String roomName = it.next();//获得班级的名字
HashMap<Integer,String> room = school.get(roomName);//通过班级的名字获得班级位置
System.out.println(roomName);
getStudent(room);//通过班级位置获得每个学生的信息
}

}

private static void getStudent(HashMap<Integer, String> room) {
//获得学生信息方法
Iterator<Integer> it = room.keySet().iterator();
while(it.hasNext()){
Integer num = it.next();
String name = room.get(num);
System.out.println(num+":"+name);
}
}

}


总结

对于集合框架的学习,应当理解每个集合的底层数据结构,只有这样才能知道具体问题时该利用哪个集合。这一讲体现了一个重要的学习方法,即先学共性内容,再学具体内容。也就是先看父类,再看子类,这种学习方法在今后的自学中也要利用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: