Java编程思想——第17章 容器深入研究(一)

Wesley13
• 阅读 571

  这一章将学习散列机制是如何工作的,以及在使用散列容器时怎么样编写hashCode()和equals()方法。

一、容器分类

  先上两张图 来概况完整的容器分类 再细说都为什么会有那些特性。

Java编程思想——第17章 容器深入研究(一)  

 Java编程思想——第17章 容器深入研究(一)

二、Collection的功能方法

int size();容器大小 

boolean isEmpty();容器内没有元素,返回true

boolean contains(Object o);容器内含有此参数,返回true

Iterator<E> iterator(); 返回一个Iterator<E> 用于遍历

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

<T> T[] toArray(T[] a); 返回一个包含所有容器内元素的数组,但返回类型为T而不简单是Object

boolean add(E e);像容器添加内容添加失败返回false(可选的)

boolean remove(Object o);移除一个元素,成功返回true(可选的)

boolean containsAll(Collection<?> c);若包含参数中的所有元素,返回true

boolean addAll(Collection<? extends E> c);添加参数中所有元素,有任意元素添加成功则返回true(可选的)

boolean removeAll(Collection<?> c);一处参数中所有元素,有任何元素移除则返回true(可选的)

default boolean removeIf(Predicate<? super E> filter) * 1.8新增 移除满足参数参数条件的元素(可选的)举例:names.removeIf(a->a.startsWith("徐")); 删除开头为徐的名字 strings.removeIf(a->a.equals("hello")); 删除hello这个元素。

boolean retainAll(Collection<?> c);只保存参数中元素,如果Collection发生变化返回true(可选的)

void clear();清空集合(可选的)

boolean equals(Object o);于其他集合对比是否相等

int hashCode();返回集合的哈希值:一个用来进行hash操作的整型代号

default Spliterator<E> spliterator()* 1.8新增 并行遍历迭代器 不影响主线程的遍历器 举例:

public static void main(String[] args) {
        List<String> list = new LinkedList<>();
        for (int i = 0; i < 20000; i++) {
            list.add("" + i);
        }
        list.spliterator().forEachRemaining(e -> System.out.println(e)); System.err.println("end"); }

输出结果:

Java编程思想——第17章 容器深入研究(一)

default Stream<E> stream()返回一个顺序流

default Stream<E> parallelStream()返回一个并行流 Java8新增Stream:Java8两大特性(一)——Stream注意:Collection中不包括随机访问所选元素的get()方法,因为Collection包括Set,而Set是自己维护内部顺序的,这使得随机访问没有意义,因此如果想访问Collection中的元素,就必须使用迭代器。

三、可选方法

  执行各种添加和移除操作在Collection中都是可选操作。这意味着实现类并不需要为这些方法提供功能定义。如果一个操作时可选的,编译器仍旧会严格要求你只能调用该接口中的方法,并且将Collection当作参数接受的大部分方法只会从该Collection中读取,而Collection的读取方法都是不可的。

  为什么要将方法定义为可选呢?原因很简单 就是防止在设计中出现接口爆炸的情况。

未获支持的操作:

  最常见的未获支持操作,都是源于背后有固定尺寸的数据结构支持的容器。比如:Arrays.asList()会生成一个List,它是基于固定大小的数组,仅支持那些不会改变数组大小的操作。任何会引起对底层数据结构的尺寸进行修改的方法 都会产生一个UnsupportedOperationException异常,以表示对未获支持操作的调用。应该把Arrays.asList()的结果作为构造器的参数传递给任何Collection(或者使用addAll())来生成可以使用所有方法的普通容器。

四、List的功能方法

 排除Collection已包含的方法外还增加了

boolean addAll(int index, Collection<? extends E> c);从索引位置插入参数中元素

default void replaceAll(UnaryOperator<E> operator) *1.8新增 将几何中元素替换成参数中的 举例:

List<Integer> list = new ArrayList();
        list.add(1);
        list.add(2);
        list.replaceAll(a -> a + 1);//将元素更新为+1的元素

default void sort(Comparator<? super E> c) c:自定义排序规则 举例:

List<User> list = new ArrayList();
        list.add(u1);
        list.add(u2);
        list.sort((o1, o2) -> {
            Integer age1 = o1.getAge();
            Integer age2 = o2.getAge();
            return age1.compareTo(age2); }); //自定义年龄排序

E get(int index); 获取索引位置的元素

E set(int index, E element); 将元素放入索引位置

void add(int index, E element); 在索引位置增加元素

E remove(int index); 移除索引位置的元素

int indexOf(Object o); 返回元素第一次出现时的索引位置

int lastIndexOf(Object o); 返回元素最后一次出现时的索引位置

ListIterator<E> listIterator(); 迭代器

ListIterator<E> listIterator(int index); 从索引位置迭代

List<E> subList(int fromIndex, int toIndex); 按照索引开始结束位置截取------LinkLIst独有的方法-------

public void addFirst(E e) 在首位增加

public void addLast(E e) 在尾部增加public E removeFirst(E e) 移除首位

public E removeLast(E e) 移除尾部这四个方法的合理利用可以利用LinkList实现栈(先进后出)和队列(先进先出)

五、Set和存储顺序

  不同的Set实现具不同的行为,并且对于在特定的Set中放置的元素类型也有不同的要求。

  Set(interface): 存入Set的每个元素都必须是唯一的,因为set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set和Collection有完全一样的接口。Set接口不保证维护元素的次序。

  HashSet *:为快速查找而设计的Set。存入HashSet的元素必须定义hashCode()。因为速度所以首选,神秘的排序。

  TreeSet:保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列。元素必须实现Comparable接口。

  LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素顺序(插入顺序)。于是在使用迭代器遍历Set时,结果会按元素插入顺序显示,元素也必须实现hashCode()方法。

  必须为Set创建equals()方法,只有HashSet和LinkHashSet需要hashCode()方法。但是良好的编程风格应该是重写equals()时跟着重写hashCode()。

如何为Set创建自定义元素类型:

class SetType {
    Integer i;

    String str;

    @Override
    public boolean equals(Object o) {
        return o instanceof SetType && (i.equals(((SetType) o).i)) && (str.equals(((SetType) o).str));
    }
}

class HashType extends SetType {
    /**
     * 这里涉及到如何重写hashCode:
     * 1.取一个初始值17
     * 2.对每一个重要字段(equals()方法里面比较的字段)进行一下操作:
     * a.filedHashValue = filed.hashCode();
     * b.result = result*31+filedHashValue;
     */
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + (i == null ? 0 : i.hashCode());
        result = 31 * result + (str == null ? 0 : str.hashCode());
        return result;
    }
}

class TreeType extends SetType implements Comparable<TreeType> {

    /**
     * compare要指定比较字段
     */
    @Override
    public int compareTo(TreeType arg) {
        return (arg.i < i ? -1 : (arg.i.equals(i) ? 0 : 1));
    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这