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

一、容器分类

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

二、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");
}

输出结果:

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));
}
}

Java编程思想——第17章 容器深入研究(一)的更多相关文章

  1. Java编程思想——第17章 容器深入研究 读书笔记(三)

    七.队列 排队,先进先出. 除并发应用外Queue只有两个实现:LinkedList,PriorityQueue.他们的差异在于排序而非性能. 一些常用方法: 继承自Collection的方法: ad ...

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

    六.队列 排队,先进先出.除并发应用外Queue只有两个实现:LinkedList,PriorityQueue.他们的差异在于排序而非性能. 一些常用方法: 继承自Collection的方法: add ...

  3. Java编程思想——第17章 容器深入研究 读书笔记(二)

    五.List的功能方法 排除Collection已包含的方法外还增加了 boolean addAll(int index, Collection<? extends E> c);从索引位置 ...

  4. Java编程思想——第17章 容器深入研究 读书笔记(一)

    这一章将学习散列机制是如何工作的,以及在使用散列容器时怎么样编写hashCode()和equals()方法. 一.容器分类 先上两张图 来概况完整的容器分类 再细说都为什么会有那些特性. 二.填充容器 ...

  5. Java编程思想——第17章 容器深入研究 读书笔记(四)

    九.散列与散列码 HashMap使用equals()判断当前的键是否与表中存在的键相同. 正确的equals()方法需满足一下条件: 1)自反性.x.equals(x) 是true; 2)对称性.x. ...

  6. Java编程思想(11~17)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第十一章 持有对象 11.1 泛型和类型安全的容器>eg: List<St ...

  7. Java编程思想 第21章 并发

    这是在2013年的笔记整理.现在重新拿出来,放在网上,重新总结下. 两种基本的线程实现方式 以及中断 package thread; /** * * @author zjf * @create_tim ...

  8. java编程思想笔记(第一章)

    Alan Kay 第一个定义了面向对象的语言 1.万物皆对象 2.程序是对象的集合,他们彼此通过发送消息来调用对方. 3.每个对象都拥有由其他对象所构成的存储 4.每个对象都拥有其类型(TYpe) 5 ...

  9. Java编程思想——第14章 类型信息(一)

    运行时类型信息使得你可以在程序运行时发现和使用类型信息.Java是如何让我们在运行时识别对象和类的信息得呢? 主要有两种方式:1.传统RTTI,他假定我们在编译期间已经知道了所有类型:2.反射,它允许 ...

随机推荐

  1. ThreadLocal 源码解读

    一.引入 public class Thread implements Runnable { /* 前面略 */ /* ThreadLocal values pertaining to this th ...

  2. DevOps on DevCloud|如何采用流水线践行CI/CD理念【华为云技术分享】

    [摘要] 持续集成/持续交付(CI/CD,Continuous Integration/Continuous Deployment)在DevOps CMALS理念中具有支柱性地位,因而CI/CD流水线 ...

  3. 如何不用BPM配置时间

    详细方案 配置时间 您需要同步消息接口(JDBC)和异步消息接口(对JEDBCReceiver的响应).对于SAP BAPI,我们不需要消息接口. 注意:CIMS是数据库系统 消息接口(请求/响应) ...

  4. 全新一代云服务器S6,重新定义性价比

    S6通用计算型云服务器,搭载全新一代处理器,配套华为自研高性能智能网卡,计算与网络性能全面升级.S6进一步强化高性价比定位,满足企业性能要求的同时,降低中小企业上云成本. 更多详情请访问ECS产品介绍 ...

  5. list tuple dict 方法

    >>> dir(list)['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir_ ...

  6. golang数据结构之总结

    golang语言的一些数据结构实现,包括: 队列(单队列.循环队列) 链表(单链表.双链表.循环链表(解决约瑟夫环问题)) 栈(实现加减乘除计算) 递归之迷宫问题 哈希表(员工管理系统) 树(三种遍历 ...

  7. luogu P4343 [SHOI2015]自动刷题机 |二分答案

    题目描述 曾经发明了信号增幅仪的发明家 SHTSC 又公开了他的新发明:自动刷题机--一种可以自动 AC 题目的神秘装置. 自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序. ...

  8. react-native StatusBar透明

    目录 一 react-native 自定义AppStatusBar 二 配置 android 一 react-native 自定义AppStatusBar 透明 StatusBar字体黑色, 否则是白 ...

  9. Cannot forward after response has been committed问题的解决

    Cannot forward after response has been committed问题解决及分析 通过TOMCAT把系统启动,可以正常登陆门户,登陆进去选择子系统的时候点击登陆的时候,可 ...

  10. 一份详细的 Matplotlib入门指导

    hMatplotlib是最受欢迎的二维图形库,但有时我们很难做到得心应手的去使用. 如何更改图例上的标签名称? 如何设置刻度线? 如何将比例更改为对数? 如何在我的情节中添加注释和箭头? 如何在我的图 ...