30天搞定Java--day23

每日一考和复习

每日一考

  1. 什么是枚举类?枚举类的对象声明的修饰符都有哪些?
1.类中的对象的个数是确定的,有限个
2.private static final
  1. 什么是元注解?说说Retention和Target元注解的作用
1.对现有的注解进行解释说明的注解
2.Retention:指明所修饰的注解的生命周期
  Target:的作用是限定注解可作用的元素
  1. 比较throw 和 throws 的异同
1.throw生成一个异常对象,并抛出。使用在方法内部,自动抛出异常对象
2.throws处理异常的方式,使用在方法声明处的末尾
  1. 谈谈你对同步代码块中同步监视器和共享数据的理解及各自要求。
1.同步监视器:俗称锁,任何一个类的对象都可以充当锁,所有线程必须共用同一个锁
2.共享数据:需要使用同步机制将操作共享数据的代码包起来。不能包多了,也不能包少了。

复习
day22的学习内容


集合

Java集合框架概述

  1. 集合、数组都是对多个数据进行存储操作的结构,简称Java容器。
    说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库等)

  2. 数组在存储多个数据方面的特点:
    一旦初始化以后,其长度就确定了
    数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了

  3. 数组在存储多个数据方面的缺点:
    ①一旦初始化以后,其长度就不可修改。
    ②数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便,同时效率不高
    ③获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
    ④数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足


集合框架

//常用的接口和实现类
|----Collection接口:单列集合,用来存储一个一个的对象
    |----List接口:存储有序的、可重复的数据   
        |----ArrayList、LinkedList、Vector
    |----Set接口:存储无序的、不可重复的数据
        |----HashSet、LinkedHashSet、TreeSet

|----Map接口:双列集合,用来存储一对(key - value)一对的数据
    |----HashMap、LinkedHashMap、TreeMap、Hashtable、Properties

Collection接口方法

  1. 添加
    add(Object obj)
    addAll(Collection coll)
Collection coll = new ArrayList();

//add(Object e):将元素e添加到集合coll中
coll.add("AA");
coll.add("BB");
coll.add(123);//自动装箱
coll.add(new Date());

//addAll(Collection coll1):将coll1集合中的元素添加到当前的集合中
Collection coll1 = new ArrayList();
coll1.add(456);
coll1.add("CC");
coll.addAll(coll1);
  1. 获取有效元素的个数
    size()
System.out.println(coll.size());
  1. 清空集合
    void clear()
coll.clear();
  1. 是否是空集合
    boolean isEmpty()
System.out.println(coll.isEmpty());
  1. 是否包含某个元素
    boolean contains(Object obj):是通过元素的equals方法来判断是否是同一个对象
    boolean containsAll(Collection c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较
//contains(Object obj)
boolean contains = coll.contains(123);
System.out.println(contains);
System.out.println(coll.contains(new String("Tom")));

//containsAll(Collection coll1)
Collection coll1 = Arrays.asList(123, 4567);
System.out.println(coll.containsAll(coll1));
  1. 删除
    boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
    boolean removeAll(Collection coll):取当前集合的差集
coll.remove(new Person("Jerry", 20));
System.out.println(coll);

Collection coll1 = Arrays.asList(123, 456);
coll.removeAll(coll1);
System.out.println(coll);
  1. 取两个集合的交集
    boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c
Collection coll1 = Arrays.asList(123,456,789);
coll.retainAll(coll1);
System.out.println(coll);
  1. 集合是否相等(有序)
    boolean equals(Object obj)
Collection coll1 = new ArrayList();
coll1.add(456);
coll1.add(123);
coll1.add(new Person("Jerry", 20));
coll1.add(new String("Tom"));
coll1.add(false);
System.out.println(coll.equals(coll1));
  1. 转成对象数组
    Object[] toArray()
Object[] arr = coll.toArray();
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
  1. 获取集合对象的哈希值
    hashCode()
System.out.println(coll.hashCode());
  1. 遍历
    iterator():返回迭代器对象,用于集合遍历
Iterator iterator = coll.iterator();

Iterator迭代器接口

  • Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素

  • GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。迭代器模式,就是为容器而生

  • Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象

  • Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创建Iterator 对象,则必须有一个被迭代的集合

    扫描二维码关注公众号,回复: 10970171 查看本文章
  • 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前

  • 注意:
    Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法
    如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException

  1. hasNext()判断是否存在下一个元素
    Next()获取下一个元素
//遍历集合
iterator = coll.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
  1. remove()删除当前元素
//删除集合中"Tom"
Iterator iterator = coll.iterator();
while (iterator.hasNext()) {
    Object obj = iterator.next();
    if ("Tom".equals(obj)) {
        iterator.remove();
    }
}

Collection子接口之一:List接口

一、list接口框架

|----Collection接口:单列集合,用来存储一个一个的对象
   |----List接口:存储有序的、可重复的数据。  -->“动态”数组,替换原有的数组
       |----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
       |----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
       |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储

二、ArrayList的源码分析
① jdk 7情况下

 ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
 list.add(123);//elementData[0] = new Integer(123);
 ...
 list.add(11);//如果此次的添加导致底层elementData数组容量不够,则扩容

默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中
结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)

② jdk 8中ArrayList的变化:

 ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没有创建长度为10的数组
 list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
 ...

后续的添加和扩容操作与jdk 7 无异

③ 小结:jdk7中的ArrayList的对象的创建类似于单例的饿汉式,而jdk8中的ArrayList的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存


三、LinkedList的源码分析

LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象。

其中,Node(LinkedList的内部类)定义为:体现了LinkedList的双向链表的说法
private static class Node<E> {
	E item;
	Node<E> next;
	Node<E> prev;
	
	Node(Node<E> prev, E element, Node<E> next) {
		this.item = element;
		this.next = next;
		this.prev = prev;
	}
}

四、Vector的源码分析
jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组;在扩容方面,默认扩容为原来的数组长度的2倍

面试题:ArrayList、LinkedList、Vector三者的异同?
同:三个类都是实现了List接口,存储数据的特点相同:存储有序的、可重复的数据
不同:参考list接口框架


五、List接口中的常用方法

  1. void add(int index, E element):在index位置插入element元素
//boolean add(E e):在末尾插入e
ArrayList list = new ArrayList();
list.add(123);
list.add(456);
list.add("AA");
list.add(new Person("Tom", 12));
list.add(456);
System.out.println(list);

//void add(int index, E element):在index位置插入element元素
list.add(1, "BB");
System.out.println(list);
  1. boolean addAll(Collection<? extends E> c):将c中的所有元素添加进来
//boolean addAll(Collection<? extends E> c):将c中的所有元素添加进来
List list1 = Arrays.asList(1, 2, 3);
list.addAll(list1);
System.out.println(list.size());
//boolean addAll(int index, Collection<? extends E> c):在index处加入c中的所有元素
  1. E get(int index):获取指定index位置的元素
System.out.println(list.get(0));
  1. int indexOf(Object obj):返回obj在集合中首次出现的位置
int index = list.indexOf(4567);
System.out.println(index);
  1. int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
System.out.println(list.lastIndexOf(456));
  1. E remove(int index):移除指定index位置的元素,并返回此元素
Object obj = list.remove(0);
System.out.println(obj);
System.out.println(list);
  1. E set(int index, E element):设置指定index位置的元素为element
list.set(1, "CC");
System.out.println(list);
  1. List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合,左闭右开
List subList = list.subList(2, 4);
System.out.println(subList);
System.out.println(list);

总结:常用方法
增:add(Object obj)
删:remove(int index) / remove(Object obj)
改:set(int index, Object ele)
查:get(int index)
插:add(int index, Object ele)
长度:size()
遍历:① Iterator迭代器方式 ② 增强for循环 ③ 普通的循环


Collection子接口之二:Set接口

一、Set接口的框架

|----Collection接口:单列集合,用来存储一个一个的对象
    |----Set接口:存储无序的、不可重复的数据   -->高中讲的“集合”
        |----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
            |----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历
               对于频繁的遍历操作,LinkedHashSet效率高于HashSet
        |----TreeSet:可以按照添加对象的指定属性,进行排序

二、Set接口的概述

  1. Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法

  2. 向Set(主要指:HashSet、LinkedHashSet)中添加的数据,其所在的类一定要重写hashCode()和equals()
    要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码
    重写两个方法的小技巧:对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值


三、Set的特点
存储无序的、不可重复的数据
以HashSet为例说明:

  1. 无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的
  2. 不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个

四、添加元素的过程
以HashSet为例:

我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过
某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素:
    如果此位置上没有其他元素,则元素a添加成功 --->情况1
    如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值:
        如果hash值不相同,则元素a添加成功 --->情况2
        如果hash值相同,进而需要调用元素a所在类的equals()方法:
               equals()返回true,元素a添加失败
               equals()返回false,则元素a添加成功 --->情况3

对于添加成功的情况2和情况3而言:元素a 与已经存在指定索引位置上数据以链表的方式存储

五、jdk版本的差异
jdk 7 :元素a放到数组中,指向原来的元素
jdk 8 :原来的元素在数组中,指向元素a

HashSet底层:数组+链表的结构


六、使用方法举例

Set set = new HashSet();
set.add(456);
set.add(123);
set.add(123);
set.add("AA");
set.add("CC");
set.add(new User("Tom", 12));//重写方法后才会去重
set.add(new User("Tom", 12));
set.add(129);

Iterator iterator = set.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

七、LinkedHashSet的使用
LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个数据和后一个数据
优点:对于频繁的遍历操作,LinkedHashSet效率高于HashSet

Set set = new LinkedHashSet();
set.add(456);
set.add(123);
set.add(123);
set.add("AA");
set.add("CC");
set.add(new User("Tom", 12));
set.add(new User("Tom", 12));
set.add(129);

Iterator iterator = set.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());

八、TreeSet的使用

  1. 向TreeSet中添加的数据,要求是相同类的对象,且能够比较大小
  2. 两种排序方式:自然排序(实现Comparable接口) 和 定制排序(Comparator)
  3. 自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()
  4. 定制排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals()
//User类中实现Comparable接口(按名字排序),就会按序输出
set.add(new User("Tom", 12));
set.add(new User("Jerry", 32));
set.add(new User("Jim", 2));
set.add(new User("Mike", 65));
set.add(new User("Jack", 33));
set.add(new User("Jack", 56));

Iterator iterator = set.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
//com是Comparator接口的实现类,可以匹配相应的构造器进行传参
TreeSet set = new TreeSet(com);
set.add(new User("Tom", 12));
set.add(new User("Jerry", 32));
set.add(new User("Jim", 2));
set.add(new User("Mike", 65));
set.add(new User("Mary", 33));
set.add(new User("Jack", 33));
set.add(new User("Jack", 56));

Iterator iterator = set.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());

知识补充

foreach

jdk 5.0 新增了foreach循环(增强for循环),用于遍历集合、数组

  1. 遍历集合
Collection coll = new ArrayList();
coll.add(123);
coll.add(456);
coll.add(new Person("Jerry", 20));
coll.add(new String("Tom"));
coll.add(false);

//for(集合元素的类型 局部变量 : 集合对象)
//内部仍然调用了迭代器
for (Object obj : coll) {
    System.out.println(obj);
}
  1. 遍历数组
int[] arr = new int[]{1, 2, 3, 4, 5, 6};
//for(数组元素的类型 局部变量 : 数组对象)
for (int i : arr) {
    System.out.println(i);
}
发布了42 篇原创文章 · 获赞 68 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42224119/article/details/105454359
今日推荐