java基础-容器专题-Collection-Map

容器


容器

1.Collection:存储着对象的集合

对象数组:
person[] p = new person[5];

缺点:不能变化
为了满足需求,java提供了容器:集合。

集合和数组的区别:

集合:

  1. 长度可以发生改变
  2. 只能存储对象类型,引用类型
  3. 可以存储任意类型的对象

数组:

  1. .长度固定
  2. 可以存储基本类型,也可以存储对象类型
  3. 只能存储同一种类型的元素

Collection集合定义的方法:

  1. 添加功能
    boolean add(Object e):往集合中添加一个元素。
    boolean addAll(Collection c):往集合中添加一个集合的元素。

  2. 删除功能
    void clear():移除集合中的所有元素。
    boolean remove(Object o):移除集合中指定的一个元素。删除一个就返回true
    boolean removeAll(Collection c):移除集合中指定的一个集合的元素。

  3. 判断功能
    boolean contains(Object o):判断集合中是否包含指定的元素。
    boolean containsAll(Collection c):判断集合中是否包含指定的一个集合的元素。全部包含才包含,fanhitrue、
    boolean isEmpty():判断集合是否为空。

  4. 遍历功能
    Iterator iterator() 迭代器。用于获取集合中的元素。

  5. 长度功能
    int size():获取集合中元素的个数。

  6. :交集功能
    boolean retainAll(Collection c):
    假设A,B两个集合做交集。A交集B。
    返回值表示的意思是A集合是否发生过改变。
    交集的结果保存在A集合中。
    B集合不发生改变。

  7. :集合转数组
    Object[] toArray():把集合转换为数组。

重点:iterator 迭代器。用于获取集合中的元素

    Object next()返回迭代的下一个元素。其实就是获取迭代器的元素。
    			获取元素,并且移动到下一个元素的位置。
    		NoSuchElementException:就是说没有元素了,你还要继续获取。
    boolean hasNext():判断迭代器中是否有元素可以被迭代。

迭代器的原理图解和源码分析图:
在这里插入图片描述

注意:

迭代器是依赖于集合而存在,并且,一般来说,集合中要有元素才有意义。
迭代器进行集合中元素的遍历:
1.通过集合对象获取迭代器对象
2.通过迭代器对象的hashNext()方法进行判断是否有元素
3.通过迭代器对象的next()方法获取元素,并移动位置

Collection c = new ArrayList();
                Iterator it = c.iterator(); // 接口的子类对象。多态
                //标准版
                while (it.hasNext()) {
    
    
                            // System.out.println(it.next());
                            String s = (String) it.next();
                            System.out.println(s);
                        }

                // 用for循环改进版
                		for (Iterator it2 = c.iterator(); it2.hasNext();) {
    
    
                			String s = (String) it2.next();
                			System.out.println(s);

迭代器的实现源码:

interface Iterator {
    
    
            	boolean hasNext();

            	E next();
            }

            interface Collection {
    
    
            	Iterator<E> iterator();
            }

            interface List extends Collection {
    
    

            }

            class ArrayList implements List {
    
    
            	public Iterator iterator() {
    
    
            		return new Itr();
            	}

            	 private class Itr implements Iterator {
    
    
            	 	boolean hasNext() {
    
    
            	 		...
            	 	}

            		E next() {
    
    
            			...
            		}
            	 }
            }

(1)、Set接口:集,无序,不可重复

继承了Collection接口和其所有方法

    SortedSet接口:
        TreeSet:基于红黑树实现
            存入TreeSet类竖线的Set集合必须实现Comparable接口
            二分查找——二叉查找树——红黑树
            红黑树的规则:
            1.结点是红色或黑色。
            2.根结点是黑色。
            3.每个叶子结点都是黑色的空结点(NIL结点)。
            4 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)
            5.从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。

            红黑树从根到叶子的最长路径不会超过最短路径的2倍


    HashSet:哈希表实现
	       哈希表是一个元素是链表的数组
	       存储的时候是按照对象的哈希值作为数组的索引进行存储的
    LinkedHashSet:双向链表,有序,唯一
    		底层数据结构是链表和哈希表组成
	        由链表保证元素有序
	        由哈希表保证元素唯一
泛型接口:
    Collection.sort() 对序列中的元素进行排序,
由于Set集合中的元素是无序的,如果要对一个student对象进行打印输出,编译器会报错ClassCastException cannot be cast to java.lang.Comparable

    排序有两种方法,一、使用元素的自然顺序对元素进行排序,或者二、根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法,无参构造方法,默认采用的是自然排序。

    默认情况下,要想实现自然排序(无参构造方法),要让集合中的元素所属的类就必须实现Comparable接口,再重写该接口中的方法的时候,去按照需求来实现代码比较即可。
  1. Comparable接口 定义默认的排序规则——可比较的
    实现了该接口表示:这个类的实例可以比较大小,可以进行自然排序
    定义了默认的比较规则
    其实现类需实现compareTo()方法
    comparaTo()方法返回正数表示大,负数表示小,0表示相等
  2. Comparator接口 定义临时比较规则
    其实现类需要实现compare()方法
    Comparator和Comparable都是Java集合框架的成员
HashSet:
  1. 储存字符串或者对象并遍历,遍历时需要进行排序,与父类Collection接口的排序原则一致
  2. HashSet如何保证元素的唯一性?
    去除重复元素需要重写hashCode()和equals()方法
    如果两个对象的成员变量值都相同,则为同一个对象。也就是同一个元素。
TreeSet:底层数据结构是二叉树
1. 遍历元素时对元素进行排序输出,因为是无序的,不排序的话会报错。(与父类Collection接口的排序原则一致)
                 排序有两种方法,一、使用元素的自然顺序对元素进行排序,或者二、根据创建 set 时提供的 Comparator 进行排序
2. TreeSet如何保证元素的唯一性?
       TreeSet如何保证元素的唯一性和排序的呢?
                唯一:根据返回值是否是0来决定。如果返回值是0,说明元素重复,就不再添加元素。
                排序:
                		正:说明数据大,往后放。
                		0:说明重复。不添加。
                		负:说明数据小,往前放。
                		A:自然排序---元素具备比较性
                		    无参构造   让集合中被存储的元素所属的类实现Comparable接口
                		B:比较器排序---集合具备比较性
                             带参构造  让创建集合对象的时候,接收一个Comparator接口的子类对象
                需求:
                		A:去除重复。如果成员变量值都相同,则为同一个元素。
                		B:我想按照姓名的长度进行排序。(主要条件)

                自定义对象:
                		Student:name,age

                Exception in thread "main" java.lang.ClassCastException: cannot be cast to java.lang.Comparable

                Comparable c = (Comparable)(new Student());

                默认情况下,要想实现自然排序,元素所属的类就必须实现Comparable接口。
LinkedHashSet:

底层由链表和哈希表组成
由链表保证有序
由哈希表保证唯一

JDK5的新特性:静态导入、可变参数

导入:import 包名…类名
静态导入:import static 包名…类名.方法名; 静态方法。
可变参数
格式:
修饰符 返回值类型 方法名(数据类型… 变量) {
}
A:数据类型…其实是该类型的一个数组。而且这个数组是自动包装的。
B:可变参数用法的时候,要注意类型问题。
C:如果一个方法有可变参数,那么,可变参数一定在最后的位置。

(2)、 List接口:序列,排列有序,可重复

 List定义的方法:
        A:添加功能
            void add(int index,Object element):在指定的位置添加元素。
        B:获取功能
            Object get(int index):获得指定索引位置的元素 
        C:列表迭代器
            ListIterator listIterator()
        D:删除功能
            Object remove(int index):删除指定索引位置的元素,并返回该元素。
        E:修改功能
            Object set(int index,Object element):用指定的元素修改指定位置的元素,并把修改前的元素返回。
	
		
    ① ArrayList:动态数组
    		优点:可变的数组
    		缺点:指定的索引位置插入对象、删除对象需要移动数组
    ② Vector:动态数组 + 线程安全
    ③  LinkedList:双向链表的动态数组
    		优点:方便插入和删除对象,只需要改变指针指向即可
    		缺点:随机访问时效率低,需要对链表进行遍历。
问:ListIterator和iterator的区别?

iterator是listIterator的父亲,listIterator继承了iterator接口,iterator接口中该有的方法在listIterator中都有
listIterator可以正向遍历也可以逆向遍历,但是listIterator必须先正向遍历后才能逆向遍历
代码:

 Iterator it = list.iterator();
        While (it.hashNext()){
    
    
            String s = (String) it.next();
            if("lisi".equals(s)){
    
    
                list.add("zhaoliu");
            }
        }
并发修改异常的产生原因及解决方案

问:用迭代器遍历集合的时候,用集合修改集合有没有问题?如果有,怎么解决?
ConcurrentModificationException:并发修改异常
因为迭代器是依赖于集合存在的,我们在使用迭代器的过程中,用集合往集合中添加元素,而并没有重新获取迭代器,所以报错。
原因: 在迭代器迭代的过程中,是不能通过集合去修改集合的。
解决方案
A:用集合本身遍历集合,用集合去修改集合。
集合实现。添加成功,元素添加到末尾

for(int x=0;x<list.size();x++){
    
    
                        String s = (String)list.get(x);
                        if("lisi".equals(s)){
    
    
                            list.add("zhaoliu");
                        }
                    }

B:用迭代器迭代,用迭代器修改元素。
迭代器实现 listIterator中才有add方法 Iterator中没有。添加成功,遍历到哪里,添加到哪里

 listIterator lit = list.listIterator();
                   While (it.hashNext()){
    
    
                       String s = (String) it.next();
                       if("lisi".equals(s)){
    
    
                           list.add("zhaoliu");
                        }
                   }

(3)、 Queue接口

LinkedList:双向队列
PriorityQueue:堆结构实现,可实现优先队列

2.Map:存储着键-值对的映射表,能够实现key快速查找value

SortedMap接口:
    TreeMap:红黑树实现
HashTable:
LinkedHashMap:
HashMap:哈希表实现

Map:
 1. Map中键值对以Entry类型的对象实例形式存在
 2. key值不能重复,value可以
 3. 每个键最多只能映射到一个值
 4. Map接口提供了分别返回key值集合、value值集合以及Entry(键值对)集合的方法
 5. Map支持泛型,Map<K,V>

HashMap类:
    HashMap是Map的实现类,基于哈希表实现的![在这里插入图片描述](https://img-blog.csdnimg.cn/20200614153549518.bmp?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NjU1NjAy,size_16,color_FFFFFF,t_70)
    HashMap中的Entry对象是无序排列的
    Key值和value值都可以为null,但是一个HashMap只能有一个key值为null的映射(key值不可重复)

1、TreeMap

2、HashTable

3、LinkedHashMap

4、HashMap

原理
扩容机制
动态扩容中出现的问题

5、ConcurrentHashMap

Map数组中的遍历功能

map数组中的遍历功能

TreeMap算法:使用Map统计字符串中每一个字符出现的次数

使用Map统计字符串中每一个字符出现的次数

import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

/*
 键盘录入字符串,统计字符串中每个字符出现的次数。
 "helloworld"

 "d(1)e(1)h(1)l(3)o(2)r(1)w(1)"
 */
public class TreeMapDemo {
    
    
	public static void main(String[] args) {
    
    
		// 键盘录入字符串
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入一个字符串:");
		String line = sc.nextLine();

		// 创建一个Map集合,经过简单的分析,我们知道创建的是TreeMap集合
		TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();

		// 把字符串转成字符数组
		char[] chs = line.toCharArray();

		// 遍历数组得到每一个字符
		for (char ch : chs) {
    
    
			// 拿这个字符到TreeMap集合中找值
			Integer i = tm.get(ch);

			// 如果是null
			if (i == null) {
    
    
				tm.put(ch, 1);
			} else {
    
    
				// 如果不是null
				i++;
				tm.put(ch, i);
			}
		}

		StringBuilder sb = new StringBuilder();
		// 遍历TreeMap集合,拼接成一个字符串
		Set<Character> set = tm.keySet();
		for (Character key : set) {
    
    
			Integer value = tm.get(key);
			sb.append(key).append("(").append(value).append(")");
		}
		String result = sb.toString();

		// 输出结果
		System.out.println(result);
	}
}

3. 泛型

   集合中的元素可以是任意类型的对象(对象的引用), 当把对象放入集合中,则会忽略他的类型,当做object处理
1. 泛型则是规定了集合只可以存放特定类型的对象
2. 泛型集合中,不能添加泛型规定的类型及其子类型以外的对象,否则会报错
3. 泛型集合可以添加泛型的子类型的对象实例


泛型:是一种把明确数据类型的工作推迟到创建对象或者调用方法的时候才去明确的一种特殊的数据类型。
格式:
		<数据类型>
		注意:如果没有给出数据类型,那么,默认是Object类型。
泛型的好处:
		A:优化了程序设计,解决了黄色警告线问题。
		B:把运行时期的问题提前到了编译期间解决了。
		C:避免了强制类型转换。
		

 泛型集合:泛型类型 泛型子类型
    1. 泛型集合中的限定类型不能使用基本的数据类型
    2. 可以使用包装类限定存入的基本数据类型
        int -> Integer

4.Collection.sort() 对序列中的元素进行排序

Comparable接口   定义默认的排序规则——可比较的
    1.  实现了该接口表示:这个类的实力可以比较大小,可以进行自然排序
    2   定义了默认的比较规则
    3.  其实现类需实现compareTo()方法
    4.  comparaTo()方法返回正数表示大,负数表示小,0表示相等

Comparator接口    定义临时比较规则
    1.  其实现类需要实现compare()方法
    2.  Comparator和Comparable都是Java集合框架的成员

5.Collections工具类

1. Collections是针对集合进行操作的工具类。
2. Collection和Collections的区别?

A:Collection 是集合的顶层接口,定义了集合中的共性功能。
B:Collections 是针对集合进行操作的工具类。提供了排序,查找等功能。

3. Collections常见的功能:
	A:排序 public static <T> void sort(List<T> list)       
	B:二分查找 public static <T> int binarySearch(List<T> list,T key)      
	C:最大值 public static <T> T max(Collection<T> coll)         
	D:反转 public static void reverse(List list)                       
	E:随机置换 public static void shuffle(List list):随机置换     
4. 扑克牌案例:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

public class PokerDemo {
    
    
	public static void main(String[] args) {
    
    
		// 创建一个HashMap集合。
		HashMap<Integer, String> hm = new HashMap<Integer, String>();
		// 创建一个ArrayList集合。
		ArrayList<Integer> array = new ArrayList<Integer>();

		// 定义点数数组
		String[] numbers = {
    
     "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
				"K", "A", "2" };
		// 定义花色数组
		String[] colors = {
    
     "♠", "♥", "♣", "♦" };

		int index = 0;
		for (String number : numbers) {
    
    
			for (String color : colors) {
    
    
				hm.put(index, color.concat(number));
				array.add(index);
				index++;
			}
		}
		hm.put(index, "小王");
		array.add(index);
		index++;
		hm.put(index, "大王");
		array.add(index);

		// 洗牌
		Collections.shuffle(array);

		// 发牌
		// 发牌
		// 三个玩家
		TreeSet<Integer> candy = new TreeSet<Integer>();
		TreeSet<Integer> judy = new TreeSet<Integer>();
		TreeSet<Integer> lucy = new TreeSet<Integer>();
		// 底牌
		TreeSet<Integer> john = new TreeSet<Integer>();

		for (int x = 0; x < array.size(); x++) {
    
    
			if (x >= array.size() - 3) {
    
    
				candy.add(array.get(x));
			} else if (x % 3 == 0) {
    
    
				judy .add(array.get(x));
			} else if (x % 3 == 1) {
    
    
				lucy .add(array.get(x));
			} else if (x % 3 == 2) {
    
    
				john .add(array.get(x));
			}
		}

		// 看牌
		printPoker("candy", candy, hm);
		printPoker("judy", judy, hm);
		printPoker("lucy", lucy, hm);
		printPoker("john", john, hm);
	}

	public static void printPoker(String name, TreeSet<Integer> ts,
			HashMap<Integer, String> hm) {
    
    
		System.out.print(name + "的牌是:");
		for (Integer key : ts) {
    
    
			System.out.print(hm.get(key) + " ");
		}
		System.out.println();
	}
}

6. 代码测试实现

学生类
package collection;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/8 16:31
 * version 1.0
 * Description: 测试
 */

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 *学生类
 */
public class Student implements Comparable<Student>{
    
    

    public String id;

    public String name;

    public Set<Course> courses;

    public Student(String id, String name) {
    
    
        this.id = id;
        this.name = name;
        //把所选课程进行初始化 不能直接实例化Set Set为一个接口
        this.courses = new HashSet<Course>();

    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(name);
    }

    @Override
    public int compareTo(Student o) {
    
    


        return this.id.compareTo(o.id);
    }
}

课程类
package collection;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/8 16:29
 * version 1.0
 * Description: 创建课程类和学生类来理解 list 和 Arraylist
 * 课程类
 */

import java.util.Objects;

/**
 * 课程类
 * 由于只是测试 所以属性写成了公有属性
 */
public class Course {
    
    

    public String id;

    public String name;

    public Course(String id, String name) {
    
    
        this.id = id;
        this.name = name;
    }

    public Course() {
    
    

    }

    @Override
    public boolean equals(Object o) {
    
    
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        if (!(o instanceof Course))
            return false;
        Course course = (Course) o;
        if (this.name == null){
    
    
            if (course.name == null)
                return true;
            else
                return false;
        }else {
    
    
            if (this.name.equals(course.name))
                return true;
            else
                return false;
        }
    }

    @Override
    public int hashCode() {
    
    
        return Objects.hash(name);
    }
}

Set接口的Test
package collection;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/8 22:06
 * version 1.0
 * Description: 测试
 */
/**
 * 功能说明:
 *  提供备选课程
 *  创建学生对象 并给学生添加三门课程(添加在学生的courses——Set类型的属性中)
 *      显示备选课程
 *      循环三次,每次输入课程ID
 *      往学生的course属性中添加与输入的ID匹配的课程
 *      输出学生选择的课程
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 *
 */

public class SetTest {
    
    

    public List<Course> coursesToSelect;

    public Student student;

    public SetTest() {
    
    
        coursesToSelect = new ArrayList<Course>();
    }



    /**
     * 用于往coursesToSelect中添加备选课程
     */
    public void testAdd() {
    
    
        // 创建一个课程对象,并通过调用add方法,添加到备选课程List中
        Course cr1 = new Course("1", "数据结构");
        coursesToSelect.add(cr1);
        Course temp = (Course) coursesToSelect.get(0);

        Course cr2 = new Course("2", "C语言");
        coursesToSelect.add(0, cr2);
        Course temp2 = (Course) coursesToSelect.get(0);

        Course[] course = {
    
     new Course("3", "离散数学"), new Course("4", "汇编语言") };
        coursesToSelect.addAll(Arrays.asList(course));
        Course temp3 = (Course) coursesToSelect.get(2);
        Course temp4 = (Course) coursesToSelect.get(3);

        Course[] course2 = {
    
     new Course("5", "高等数学"), new Course("6", "大学英语") };
        coursesToSelect.addAll(2, Arrays.asList(course2));
        Course temp5 = (Course) coursesToSelect.get(2);
        Course temp6 = (Course) coursesToSelect.get(3);

    }

    /**
     * 通过for each方法访问集合元素
     *
     * @param
     */
    public void testForEach() {
    
    
        System.out.println("有如下课程待选(通过for each访问):");
        for (Object obj : coursesToSelect) {
    
    
            Course cr = (Course) obj;
            System.out.println("课程:" + cr.id + ":" + cr.name);
        }
    }

    /**
     * 测试List的contains方法
     */
    public void testListContains(){
    
    
        //取得备选课程序列的第0个元素
        Course course = coursesToSelect.get(0);
        //打印输出coursesToSelect是否包含course对象
        System.out.println("取得课程:" + course.name);
        System.out.println("备选课程中是否包含课程:" + course.name +"; "+
                coursesToSelect.contains(course));

        System.out.println("请输入课程名称:");
        Scanner sc = new Scanner(System.in);
        String name = sc.next();
        //创建一个新的课程对象,ID和名称,与course对象完全一样
        Course course2 = new Course();
        course2.name = name;
        System.out.println("新创建课程:" + course2.name);
        System.out.println("备选课程中是否包含课程: " + course2.name + ", " +
                coursesToSelect.contains(course2));
        // 通过indexOf方法来取得某元素的索引位置
        if (coursesToSelect.contains(course2))
            System.out.println("课程:" + course2.name + "的索引位置为:" +
                    coursesToSelect.indexOf(course2));
    }

    /**
     * 创建学生对象并选课
     */
    public void createStudentAndSelectCourse(){
    
    
                // 创建一个学生对象
        Student student = new Student("1", "小明");
        System.out.println("欢迎学生:" + student.name + "选课!");
        // 创建一个Scanner对象,用来接收从键盘输入的课程ID
        Scanner console = new Scanner(System.in);

        for (int i = 0; i < 3; i++) {
    
    
            System.out.println("请输入课程ID");
            String courseId = console.next();
            for (Course cr : coursesToSelect) {
    
    
                if (cr.id.equals(courseId)) {
    
    
                    student.courses.add(cr);
                    /**
                     * Set中,添加某个对象,无论添加多少次, 最终只会保留一个该对象(的引用), 并且保留的是第一次添加的那一个
                     */
                    /**
                     * 可以添加空对象 但是无意义
                     */
                    // student.courses.add(null);
//                    student.courses.add(cr);
                }
            }
        }
    }

    /**
     * 测试Set的contains方法
     */
    public void testSetContains(){
    
    
        //提示输入课程名称
        System.out.println("请输入学生已选的课程名称:");
        Scanner sc = new Scanner(System.in);
        String name2 = sc.next();
        //创建一个新的课程对象,ID和名称,与course对象完全一样
        Course course2 = new Course();
        course2.name = name2;
        System.out.println("新创建课程:" + course2.name);
        System.out.println("备选课程中是否包含课程: " + course2.name + ", " +
                student.courses.contains(course2));


    }

    /**
     * @param args
     */
    public static void main(String[] args) {
    
    
        SetTest st = new SetTest();
        st.testAdd();
        st.testListContains();
        st.testForEach();

//        st.testForEachForSet(student);
//
//
//        st.createStudentAndSelectCourse();
//        st.testSetContains();
    }

    /**
     * 遍历Set方法只能用for each方法和iterator方法,不能像List方法一样使用get()方法,
     * 因为Set是无序的没有get() set()方法
     *
     */
    public void testForEachForSet(Student student) {
    
    
        // 打印输出,学生所选的课程!
        System.out.println("共选择了:" + student.courses.size() + "门课程!");
        for (Course cr : student.courses) {
    
    
            System.out.println("选择了课程:" + cr.id + ":" + cr.name);
        }
    }

}

Map接口的Test
package collection;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/9 10:27
 * version 1.0
 * Description: 测试
 */

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

/**
 *通过Map<String,Student>进行学生信息管理,其中key为学生ID,value为学生对象
 * 通过键盘输入学生信息
 * 对集合中的学生信息进行增、删、改、查操作
 */
public class MapTest {
    
    
    /**
     * 用来承装学生类型对象
     *
     */
    public Map<String,Student> students;
    /**
     * 构造器中初始化students属性
     *
     */
    public MapTest() {
    
    
        this.students = new HashMap<String, Student>();
    }

    /**
     *测试添加:输入学生ID,判断是否被占用
     * 若未被占用,则输入姓名,创建新学生对象,并且添加到students中
     */
    public void testPut(){
    
    
        //创建一个Scanner对象,用来获取输入的学生ID和姓名
        Scanner sc = new Scanner(System.in);
        int i = 0;
        while (i<3){
    
    
            System.out.println("请输入学生ID:");
            String ID = sc.next();
            //判断该ID是否被占用
            Student st = students.get(ID);
            if (st == null){
    
    
                //提示输入学生姓名
                System.out.println("请输入学生姓名:");
                String name = sc.next();
                //创建新得学生对象
                Student newStudent = new Student(ID,name);
                //通过调用students的put方法,添加ID-学生映射
                students.put(ID,newStudent);
                System.out.println("成功添加学生" + students.get(ID).name);
                i++;

            }else {
    
    
                System.out.println("该学生ID已被占用");
                continue;
            }
        }
    }

    /**
     * 测试Map的keySet方法
     */
    public void testKeySet() {
    
    
        // 通过keySet方法,返回Map中的所有“键”的Set集合
        Set<String> keySet = students.keySet();
        // 取得students的容量
        System.out.println("总共有:" + students.size() + "个学生!");
        // 遍历keySet,取得每一个键,再调用get方法取得每个键对应的value
        for (String stuId : keySet) {
    
    
            Student st = students.get(stuId);
            if (st != null)
                System.out.println("学生:" + st.name);
        }
    }
    /**
     * 测试删除Map中的映射
     */
    public void testRemove() {
    
    
        // 获取从键盘输入的待删除学生ID字符串
        Scanner console = new Scanner(System.in);
        while (true) {
    
    
            // 提示输入待删除的学生的ID
            System.out.println("请输入要删除的学生ID!");
            String ID = console.next();
            // 判断该ID是否有对应的学生对象
            Student st = students.get(ID);
            if (st == null) {
    
    
                // 提示输入的ID并不存在
                System.out.println("该ID不存在!");
                continue;
            }
            students.remove(ID);
            System.out.println("成功删除学生:" + st.name);
            break;
        }
    }
    /**
     * 通过entrySet方法来遍历Map
     */
    public void testEntrySet() {
    
    
        // 通过entrySet方法,返回Map中的所有键值对
        Set<Map.Entry<String, Student>> entrySet = students.entrySet();
        for (Map.Entry<String, Student> entry : entrySet) {
    
    
            System.out.println("取得键:" + entry.getKey());
            System.out.println("对应的值为:" + entry.getValue().name);
        }
    }

    /**
     * 利用put方法修改Map中的已有映射
     */
    public void testModify() {
    
    
        // 提示输入要修改的学生ID
        System.out.println("请输入要修改的学生ID:");
        // 创建一个Scanner对象,去获取从键盘上输入的学生ID字符串
        Scanner console = new Scanner(System.in);
        while (true) {
    
    
            // 取得从键盘输入的学生ID
            String stuID = console.next();
            // 从students中查找该学生ID对应的学生对象
            Student student = students.get(stuID);
            if (student == null) {
    
    
                System.out.println("该ID不存在!请重新输入!");
                continue;
            }
            // 提示当前对应的学生对象的姓名
            System.out.println("当前该学生ID,所对应的学生为:" + student.name);
            // 提示输入新的学生姓名,来修改已有的映射
            System.out.println("请输入新的学生姓名:");
            String name = console.next();
            Student newStudent = new Student(stuID, name);
            students.put(stuID, newStudent);
            System.out.println("修改成功!");
            break;
        }
    }
    /**
     * 测试Map中,是否包含某个Key值或者某个Value值
     */
    public void testContainsKeyOrValue() {
    
    
        // 提示输入学生id
        System.out.println("请输入要查询的学生ID:");
        Scanner console = new Scanner(System.in);
        String id = console.next();
        // 在Map中,用containsKey()方法,来判断是否包含某个Key值
        System.out.println("您输入的学生ID为:" + id + ",在学生映射表中是否存在:"
                + students.containsKey(id));
        if (students.containsKey(id))
            System.out.println("对应的学生为:" + students.get(id).name);
        // 提示输入学生姓名
        System.out.println("请输入要查询的学生姓名:");
        String name = console.next();
        // 用containsValue()方法,来判断是否包含某个Value值
        if (students.containsValue(new Student(null,name)))
            System.out.println("在学生映射表中,确实包含学生:" + name);
        else
            System.out.println("在学生映射表中不存在该学生!");
    }



    public static void main(String[] args) {
    
    
        MapTest mt = new MapTest();
        mt.testPut();
        mt.testKeySet();
//        mt.testRemove();
//        mt.testEntrySet();
        mt.testModify();
        mt.testEntrySet();
    }
}

List接口的Test
package collection;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/8 16:36
 * version 1.0
 * Description: 测试
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 *备选课程类
 */
public class ListTest {
    
    
    /**
     * 用于存放备选课程的list
     */
    public List coursesToSelect;

    public ListTest() {
    
    
        //通过构造函数对属性进行实例化
        this.coursesToSelect = new ArrayList();
    }

    /**
     * 用于往coursesToSelect中添加备选课程
     *
     * add方法往list中添加元素
     */
    public void testAdd(){
    
    
        //创建一个课程对象,并通过调用add方法,添加到备选课程List中
        Course cr1 = new Course("1", "数据结构");
        coursesToSelect.add(cr1);
        //当对象存入都变成object类型  取出时需要类型转换
        Course temp = (Course) coursesToSelect.get(0);
        System.out.println("添加了课程:" + temp.id + " : " + temp.name);

        //指定位置进行插入 会把之前添加的“数据结构”课程挤到第1个位置 新插入的在第0个位置
        Course cr2 = new Course("2", "电路基础");
        coursesToSelect.add(0,cr2);
        //当对象存入都变成object类型  取出时需要类型转换
        Course temp2 = (Course) coursesToSelect.get(0);
        System.out.println("添加了课程:" + temp2.id + " : " + temp2.name);

        Course[] course = {
    
    new Course("3", "高等数学"),new Course("4", "英语")};
        //使用Arrays.asList()方法 把course数组转换成一个list集合
        coursesToSelect.addAll(Arrays.asList(course));
        Course temp3 = (Course) coursesToSelect.get(2);
        Course temp4 = (Course) coursesToSelect.get(3);

        System.out.println("添加了两门课程:" + temp3.id + ": " + temp3.name + ";" +
                temp4.id + ": " + temp4.name);

        //进行插入到指定位置 插入到下标为2的位置
        Course[] course2 = {
    
    new Course("5", "离散数学"),new Course("6", "政治")};
        coursesToSelect.addAll(2,Arrays.asList(course2));
        Course temp5 = (Course) coursesToSelect.get(2);
        Course temp6 = (Course) coursesToSelect.get(3);

        System.out.println("添加了两门课程:" + temp5.id + ": " + temp5.name + ";" +
                temp6.id + ": " + temp6.name);

        //测试可重复添加
        coursesToSelect.add(cr2);
        //当对象存入都变成object类型  取出时需要类型转换
        Course temp0 = (Course) coursesToSelect.get(2);
        System.out.println("添加了课程:" + temp0.id + " : " + temp0.name);

    }

    /**
     * 取得list中元素的方法
     * list 中的size方法取得列表中元素的长度
     *
     */

    public void testGet(){
    
    
        int size = coursesToSelect.size();

        System.out.println("有如下课程待选");
        for (int i = 0; i <size;i++){
    
    
            Course cr = (Course) coursesToSelect.get(i);
            System.out.println("课程:" + cr.id + ":" + cr.name);
        }
    }

    /**
     * Iterator 返回在此collection的元素上进行迭代的迭代器
     * 迭代器就是会用来遍历集合中元素的 不具备存储元素的功能 依赖于集合存在 不能独立存在
     * 通过迭代器进行List遍历
     */
    public void testIterator(){
    
    
        //通过集合的iterator方法,取得迭代器的实例
        Iterator it = coursesToSelect.iterator();
        System.out.println("有如下课程待选(通过迭代器访问):");
        while (it.hasNext()) {
    
    
            Course cr = (Course)it.next();
            System.out.println("课程: " + cr.id + ": " + cr.name);
        }

    }

    /**
     * 通过for each方法访问集合元素
     */
    public void testForEach(){
    
    
        System.out.println("有如下课程待选(通过for each访问):");
        for (Object obj: coursesToSelect) {
    
    
            Course cr = (Course) obj;
            System.out.println("课程: " + cr.id + ": " + cr.name);
        }
    }


    public static void main(String[] args) {
    
    
        ListTest lt = new ListTest();
        lt.testAdd();
        lt.testGet();
        lt.testIterator();
        lt.testForEach();
    }
}

泛型的Test
package collection;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/8 21:47
 * version 1.0
 * Description: 测试
 */

/**
 *
 */
public class ChildCourse extends Course {
    
    
        //ChildCourse继承了Course类型 要调用父类的无参构造器
}



package collection;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/8 21:39
 * version 1.0
 * Description: 测试
 */

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

/**
 *
 */
public class TestGeneric {
    
    

    /**
     * 带有泛型——course的List类型属性
     */
    public List<Course> courses;

    public TestGeneric() {
    
    
        this.courses = new ArrayList<Course>();
    }

    /**
     * 测试添加
     * @param
     */
    public void testAdd(){
    
    
        Course cr1 = new Course("1","大学语文");
        courses.add(cr1);
        //泛型集合中,不能添加泛型规定的类型及其子类型以外的对象,否则会报错
        // courses.add("能否添加一些奇怪的东西呢");

        Course cr2 = new Course("2","大学英语");
        courses.add(cr2);
    }

    /**
     *测试循环遍历
     * @param
     */

    public void testForEach(){
    
    
        for (Course cr:courses) {
    
    
            System.out.println(cr.id + ":" +cr.name);
        }
    }

    /**
     *泛型集合可以添加泛型的子类型的对象实例
     * @param
     */
    public void testChild(){
    
    
        ChildCourse cc = new ChildCourse();
        cc.id = "3";
        cc.name = "我是子类型的课程对象实例";
        courses.add(cc);
    }

    public static void main(String[] args) {
    
    
        TestGeneric tg = new TestGeneric();
        tg.testAdd();
        tg.testForEach();
        tg.testChild();
        tg.testForEach();
    }
}

Collections接口的Test
import java.util.Comparator;

/**
 *
 */
public class StudentComparator implements Comparator<Student> {
    
    
    @Override
    public int compare(Student o1, Student o2) {
    
    
        // TODO Auto-generated method stub
        return o1.name.compareTo(o2.name);
    }
}

package collection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import static java.util.Collections.sort;

/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/9 17:28
 * version 1.0
 * Description:
 * 测试将要完成:
 *   1.通过Collections.sort()方法,对Integer泛型的List进行排序;
 *   2.对String泛型的List进行排序;
 *   3.对其他类型泛型的List进行排序,以Student为例。
 */


public class CollectionsTest {
    
    
    /**
     * 1.通过Collections.sort()方法,对Integer泛型的List进行排序;
     * 创建一个Integer泛型的List,插入十个100以内的不重复随机整数,
     * 调用Collections.sort()方法对其进行排序
     */


    public void testSort1() {
    
    
        List<Integer> integerList = new ArrayList<Integer>();
        // 插入十个100以内的不重复随机整数
        Random random = new Random();
        Integer k;
        for (int i = 0; i < 10; i++) {
    
    
            do {
    
    
                k = random.nextInt(100);
            } while (integerList.contains(k));
            integerList.add(k);
            System.out.println("成功添加整数:" + k);
        }
        System.out.println("-------------排序前--------------");
        for (Integer integer : integerList) {
    
    
            System.out.println("元素:" + integer);
        }
        sort(integerList);
        System.out.println("----------------排序后-------------------");
        for (Integer integer : integerList) {
    
    
            System.out.println("元素:" + integer);
        }
    }

    /**
     * 2.对String泛型的List进行排序;
     * 创建String泛型的List,添加三个乱序的String元素,
     * 调用sort方法,再次输出排序后的顺序
     */
    public void testSort2() {
    
    
        List<String> stringList = new ArrayList<String>();
        stringList.add("microsoft");
        stringList.add("google");
        stringList.add("lenovo");
        System.out.println("------------排序前-------------");
        for (String string : stringList) {
    
    
            System.out.println("元素:" + string);
        }
        sort(stringList);
        System.out.println("--------------排序后---------------");
        for (String string : stringList) {
    
    
            System.out.println("元素:" + string);
        }
    }

    /**
     * 3.对其他类型泛型的List进行排序,以Student为例。
     */

    public void testSort3() {
    
    
        List<Student> studentList = new ArrayList<Student>();
        Random random = new Random();
        studentList.add(new Student(random.nextInt(1000) + "", "Mike"));
        studentList.add(new Student(random.nextInt(1000) + "", "Angela"));
        studentList.add(new Student(random.nextInt(1000) + "", "Lucy"));
        studentList.add(new Student(10000 + "", "Beyonce"));
        System.out.println("--------------排序前---------------");
        for (Student student : studentList) {
    
    
            System.out.println("学生:" + student.id + ":" + student.name);
        }
        Collections.sort(studentList);
        System.out.println("----------------排序后------------------");
        for (Student student : studentList) {
    
    
            System.out.println("学生:" + student.id + ":" + student.name);
        }
        Collections.sort(studentList, new StudentComparator());
        System.out.println("----------------按照姓名排序后-----------------");
        for (Student student : studentList) {
    
    
            System.out.println("学生:" + student.id + ":" + student.name);
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
    
    
        CollectionsTest ct = new CollectionsTest();
		ct.testSort1();
//		ct.testSort2();
//        ct.testSort3();
    }



}

测试

在这里插入图片描述

package org.example;/**
 * Copyright (C), 2019-2020
 * author  candy_chen
 * date   2020/6/8 16:18
 * version 1.0
 * Description:
 * 创建String泛型的List,放入10条随机的字符串
 * 每条字符串的长度为10以内的随机整数
 * 每条字符串的字符都是随机生成的字符,字符可以重复
 * 每条随机生成的字符串不可以重复
 */

import java.util.*;
public class sortTest {
    
    
    public List<String> ls = new ArrayList();
    public String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678";
    Random randomInt = new Random();
    Integer k;



    public List<String> creatList(){
    
    
        for (int i=0; i<10; i++){
    
    
            StringBuffer sb = new StringBuffer();
            do {
    
    
                k = randomInt.nextInt(10);
                for (int j=0; j<k+1; j++){
    
    
                    sb.append(str.charAt(randomInt.nextInt(str.length())));
                }
            }while (ls.contains(sb));
            ls.add(sb.toString());
        }
        return ls;
    }

    public void sort(List ls){
    
    
        System.out.println("-----------排序前输出:-----------");
        for(Object str:ls){
    
    
            System.out.println(str);
        }

        Collections.sort(ls);

        System.out.println("-----------排序后输出:-----------");
        for(Object str:ls){
    
    
            System.out.println(str);
        }
    }

    public static void main(String[] args) {
    
    
        sortTest st = new sortTest();
        st.sort(st.creatList());
    }

}

一些问题

  1. Array 和 ArrayList 有何区别?
    Array 可以存储基本数据类型和对象,ArrayList只能存储对象。
    Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。

  2. Arraylist和Linkedlist的区别?内部是怎么实现的?优缺点?
    Arraylist:底层是基于动态数组实现的,默认初始化长度为10,支持动态扩容,新增加的容量大小为原来容量大小的50%。
    随机访问数组元素的效率高,向数组尾部添加元素的效率高;但是,删除数组中的数据以及向数组中间添加数据效率低,因为需要移动数组。
    优点:可变的数组
    缺点:指定的索引位置插入对象、删除对象需要移动数组

     Linkedlist:基于链表的动态数组,数据添加删除效率高,只需要改变指针指向即可,但是访问数据的平均效率低,需要对链表进行遍历。
     双向链表的动态数组
              优点:方便插入和删除对象,只需要改变指针指向即可
              缺点:1. 随机访问时效率低,需要对链表进行遍历。
    
待完善。。。。#################
  1. ConcurrentHashMap 和 Hashtable 的区别?
  2. HashSet和HashMap的区别
  3. 如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办
  4. 你了解重新调整HashMap大小存在什么问题吗?(多线程的情况下,可能产生条件竞争(race condition))
  5. 为什么的currenthashmap是线程的安全的?同样是线程类,ConcurrentHashMap 和 HashTable 在线程同步上有什么不同

集合基础学习路线图

在这里插入图片描述

说明:这是网络资料进行搜索学习理解的 若有侵权联系作者

猜你喜欢

转载自blog.csdn.net/qq_35655602/article/details/106650448
今日推荐