他山之石可以攻玉给Java初学者的学习笔记

第16章 集合类

2019-04-12  本文已影响517人  yangsg

1. 集合的概念

集合是一种数学概念,表述的是“由一个或多个确定的元素所构成的整体”。

1.1 Java中集合与数组的比较

数组

集合

1.2 集合的分类
集合的继承体系

2. 线性集合(Collection接口)

2.1 线性集合的概念

Collection接口表述的是“线性集合”,线性结构是n个数据元素的有序(次序)集合
线性集合的特征
1.集合中必存在唯一的一个"第一个元素"。
2.集合中必存在唯一的一个"最后的元素"。
3.除最后元素之外,其它数据元素均有唯一的"后继"。
4.除第一元素之外,其它数据元素均有唯一的"前驱"。

2.2 线性集合(Collection)的实现类
2.2.1 List接口

有序集合(也称为序列 )。 该界面的用户可以精确控制列表中每个元素的插入位置。 用户可以通过整数索引(下标)访问元素,并搜索列表中的元素。允许集合中存放重复的数据。
有序号可重复

2.2.1.1 ArrayList实现类

底层是基于数组实现的,方法都是线程不安全的
API方法

public class Test {

    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        System.out.println(list.size());
        list.add(new String("哈哈"));
        list.add(23);
        list.add(new Date());
        list.add("哈哈");
        list.add(3.14);
        System.out.println(list.size());
        System.out.println("插入了5个元素==========================");
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("在2位置插入了嘻嘻==========================");
        list.add(2, "嘻嘻");
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("替换2位置为嘿嘿==========================");
        list.set(2, "嘿嘿");
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("移除位置2的元素==========================");
        list.remove(2);
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("移除元素“3.14”的元素==========================");
        list.remove(3.14);
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("移除元素“哈哈”的元素==========================");
        list.remove(new String("哈哈"));
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("判断集合中是否有“哈哈”的元素==========================");
        boolean b = list.contains("哈哈");
        System.out.println(b);
        System.out.println("判断集合中是否有“3.14”的元素==========================");
        boolean x = list.contains(3.14);
        System.out.println(x);
        System.out.println("清空集合==========================");
        list.clear();
        System.out.println(list.size());
    }
}

如果遇到了集合中有元素2,且还需要移除2下标时,注意写法

list.remove(2);  //移除下标位置2的元素
list.remove(new Integer(2)); //移除集合中元素2

2.2.1.2 LinkedList实现类

底层是基于链表实现的
主要的增删改查的方法参照ArrayList类的API学习
特有API方法

将LinkedList看做为一个栈

public class Test3 {
    public static void main(String[] args) {
        LinkedList<Object> list = new LinkedList<Object>();     
        list.push("哈哈");
        list.push("嘻嘻");
        list.push(100);
        list.push(3.14);
        list.push(new Date());
        
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("查看栈顶==============================");
        Object x = list.peek(); //查看栈顶
        System.out.println(x);
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("出栈==============================");
        Object y = list.pop();
        System.out.println(y);
        System.out.println("====");
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("入栈==============================");
        list.push("abc");
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
        System.out.println("出栈==============================");
        Object z = list.poll();
        System.out.println(z);
        System.out.println("====");
        for(int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            System.out.println(o);
        }
    }
}
2.2.1.3 Vector实现类

底层是基于数组实现的,方法都是线程安全的
API方法参照ArrayList学习

笔试题/面试题
(1)ArrayList和LinkedList的区别?
本质上就是问“数组”与“链表”的区别。
ArrayList基于数组实现的,LinkedList基于链表实现
数组:在查询元素速度快,插入删除速度慢
链表:在查询元素速度慢,插入删除速度快

(2)ArrayList和Vector的区别?
ArrayList线程不安全,Vector线程安全

2.2.2 Set接口

不包含重复元素的集合。如果有元素e1和e2(e1.equals(e2) 为true),e1和e2只能保留一个元素。Set接口的特征是使用者无法控制元素的存放顺序,其存放顺序有Set接口的实现类自身的算法决定

2.2.2.1 HashSet实现类

实现算法是基于Hash表算法,存放顺序不由使用者控制,允许存放一个null值
Object类中有hashcode方法,返回int值,该int值是由对象的内存地址计算出来的
一个对象会有一个HashCode(哈希码,Hash码,HashCode),它有如下特征:

比如:字符串“哈哈”的哈希码是34,字符串“嘻嘻”的哈希码是20。
使用代码存入集合的顺序:哈哈,嘻嘻
实际集合中存储顺序:嘻嘻,哈哈

比如:字符串“哈哈”的哈希码是34,字符串“嘻嘻”的哈希码是20,字符串“嘿嘿”的哈希码也是34。
使用代码存入集合的顺序:哈哈,嘻嘻
实际集合中存储顺序:嘻嘻,(哈哈,嘿嘿)


类似的存储结构

API方法

因为Set集合无法使用下标,所以不能通过下标进行遍历访问集合中的元素。只能通过迭代器去遍历Set集合

2.2.3 Iterator(迭代器)

负责通过一个向前的“游标”不断的访问元素和移动,完成Set集合的遍历。


理解迭代器

API方法

示例:利用迭代器遍历set集合

public class Test1 {

    public static void main(String[] args) {
        HashSet<Object> set = new HashSet<Object>();
        set.add("哈哈");
        set.add(3.14);
        set.add(new Date());
        set.add("hehe");
        set.add(23);    
        set.add(12);
        System.out.println(set.size());
        
        Iterator<Object> ite = set.iterator();//获得了set集合对应的迭代器
        while(ite.hasNext()) {
            Object o = ite.next();
            System.out.println(o);
        }
    }
}

面试题/笔试题:
(1)List集合和Set集合的区别?
List集合:有序可重复,可以通过下标访问数据,存放顺序可控,允许存放重复数据
Set集合:无序不重复,不能通过下标访问数据,存放数据由实现类自己决定,重复数据只能保留一个
(2)HashSet和TreeSet的区别?
HashSet基于哈希表算法实现
TreeSet基于红黑树算法实现

很多时候使用Set集合完成去重复的操作。

3. 键值集合(Map接口)

Map集合是一种以键值对为单位,进行数据存储的一种结构,它与线性集合有所区别:线性集合一个位置上只存储一个数据,键值对集合一个位置上存储的是一个键(key)和一个值(value)。不同数据之间键(key)是不能重复的,值(value)是也可重复的。存放数据时,必须提供key和value,取得数据时一般是根据key来获取value
Map的主要实现类

3.1 HashMap和HashTable

基于哈希表算法实现存储

3.1.1 构造方法
3.1.2 API方法
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(101, "赵四");  //向集合中添加一条数据
map.put(102, "刘能");  //向集合中添加一条数据
map.put(101, "哈哈");  //替换集合中原来101这条数据
map.remove(103);
map.remove(104,"刘能"); //成功,有这对数据
map.remove(102,"aaa");//失败,虽然有102,102中不是aaa
map.clear();
String v1 = map.get(103);
String v2 = map.get(105);
System.out.println("集合中的元素个数是:"+map.size());    
Set<Entry<Integer, String>> set = map.entrySet();//得到键值对的Set集合
Iterator<Entry<Integer, String>> ite = set.iterator();//将set集合变成迭代器
while(ite.hasNext()) { //遍历迭代器
    Entry<Integer, String> e = ite.next(); //一个键值对
    System.out.println(e.getKey()+":"+e.getValue());
}
Set<Integer> kset = map.keySet(); //所有key值组成的set集合
Iterator<Integer> kite = kset.iterator(); //将set集合变成迭代器
while(kite.hasNext()) { //遍历迭代器
    int key = kite.next();
    String value = map.get(key); //取得value
    System.out.println(key+":"+value);
}
boolean x = map.isEmpty();
boolean b1 = map.containsKey(101);
boolean b2 = map.containsKey(105);
boolean b3 = map.containsValue("刘能");
boolean b4 = map.containsValue("AAA");

面试题/笔试题
(1)HashMap与HashTable的区别
HashMap是线程不安全的,HashTable是线程安全。
HashMap中允许null作为key,HashTable不允许null作为key

(2)HashMap与TreeMap的区别
HashMap底层基于Hash表算法
TreeMap底层基于二叉树算法

(3)HashMap的桶容量(扩容机制)
以默认hashmap()构造方法解释:,默认初始值16,负载因子0.75.
初始时hashmap的最大容量是16,当存储数据至12时(16*0.75),进行扩容,扩容方式是16*2=32; 当继续存储数据至24时(32*0.75),继续扩容,扩容方式32*2=64

3.2 TreeMap

基于红黑树算法实现存储
参照HashMap的API去理解

4. 泛型

泛型是用于约束集合中输入数据类型的。集合默认是可以将任何数据都放入其中,很多情况下我们需要约束集合中输入的元素类型,借助于泛型可以达到效果。
泛型的优势

约束输入类型为String

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

由于泛型约束只支持引用数据类型,如果需要约束一个整数集合,需要使用包装类

ArrayList<Integer> list = new ArrayList<Integer>();

泛型约束Employee类的集合

ArrayList<Employee> list = new ArrayList<Employee>();

泛型约束其他的集合

ArrayList<HashSet<String>> list = new ArrayList<HashSet<String>>();

for...each句式:使用变量s去遍历list集合中每(each)一个元素

ArrayList<String> list = new ArrayList<String>();
for(String s : list) {
    System.out.println(s);
}

5. Collections类(集合工具类)

主要提供了大量的关于集合操作的方法,方便操作集合

public class Test2 {

    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        Random r = new Random();
        for(int i = 0; i < 10; i++) {
            int x = r.nextInt(100);
            list1.add(x);
        }
        for(int i = 0; i < 10; i++) {
            int x = r.nextInt(100);
            list2.add(x);
        }
        System.out.println(list1);
        System.out.println(list2);
        System.out.println("=======================");
        //集合copy
        Collections.copy(list2, list1);
        
        System.out.println(list1);
        System.out.println(list2);
    }
}
public class Test3 {
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        Random r = new Random();
        for(int i = 0; i < 10; i++) {
            int x = r.nextInt(100);
            list1.add(x);
        }
        System.out.println(list1);
        Collections.sort(list1);//升序
        System.out.println(list1); 
    }
}

如果想比较的是自己编写的类,可以通过让自己的类实现Comparable接口并完成CompareTo方法
Student类

public class Student implements Comparable<Student>{
    
    private int sno;
    private String sname;
    
    public Student() {}
    
    public Student(int sno, String sname) {
        this.sno = sno;
        this.sname = sname;
    }

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    @Override
    public int compareTo(Student o) {
        if(this.sno < o.sno) {
            return -1;
        }else if(this.sno == o.sno) {
            return 0;
        }else {
            return 1;
        }
    }
}

利用sort方法进行排序

public class Test {

    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList<Student>();
        
        Student s1 = new Student(1002,"赵四");
        Student s2 = new Student(1004,"刘能");
        Student s3 = new Student(1001,"谢广坤");
        Student s4 = new Student(1003,"王大拿");
        
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        
        for(Student s : list) {
            System.out.println(s.getSno()+"\t"+s.getSname());
        }
        System.out.println("============================");
        Collections.sort(list);
        
        for(Student s : list) {
            System.out.println(s.getSno()+"\t"+s.getSname());
        }   
    }
}
public class Student{
    
    private int sno;
    private String sname;
    
    public Student() {}
    
    public Student(int sno, String sname) {
        this.sno = sno;
        this.sname = sname;
    }

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

}

编写一个比较器

public class StudentComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        if(o1.getSno() < o2.getSno()) {
            return -1;
        }else if(o1.getSno() == o2.getSno()) {
            return 0;
        }else {
            return 1;
        }
    }
}

利用sort进行排序

public class Test {

    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList<Student>();
        
        Student s1 = new Student(1002,"赵四");
        Student s2 = new Student(1004,"刘能");
        Student s3 = new Student(1001,"谢广坤");
        Student s4 = new Student(1003,"王大拿");
        
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        
        for(Student s : list) {
            System.out.println(s.getSno()+"\t"+s.getSname());
        }
        System.out.println("============================");
        Collections.sort(list, new StudentComparator());
        
        for(Student s : list) {
            System.out.println(s.getSno()+"\t"+s.getSname());
        }       
    }
}
public class Test3 {
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        Random r = new Random();
        for(int i = 0; i < 10; i++) {
            int x = r.nextInt(100);
            list1.add(x);
        }
        System.out.println(list1);
        Collections.sort(list1);//升序
        System.out.println(list1); 
        Collections.reverse(list1);//降序
        System.out.println(list1); 
    }
}
上一篇下一篇

猜你喜欢

热点阅读