疯狂java笔记_疯狂java讲义第八章笔记

第八章 java集合

8.1 java集合

集合用来保存数量不确定的数据,以及保存具有映射关系的数据。也被称为容器类。集合类都位于java.util包下。集合只能保存对象。

java集合由 collection和map两个接口派生。

8.2 Collection和Iterator接口

添加对象,删除对象,清空容器,判断容器是否为空

当使用System.out.println()时会输出[ ele1,ele2...]这是因为所有的Collection都重写了toString的方法。如果想一次访问集合中的每个元素,需要使用下面的方法遍历元素。

8.2.1 使用Lambda表达式遍历集合

Collection可以直接调用foreach(Consumer action)方法,因为Consumer是函数式接口,所以可以用Lambda表达式

8.2.2 使用java8增强的Iterator遍历集合元素

Iterator也是java集合框架的成员,但是主要用于遍历Collection中的元素,Iterator对象也被称为迭代器。

Iterator it=books.iterator();Iterator必须依赖Collection对象

it.hasNext();

it.next();

it.remove();

iterator对集合进行迭代时,只是把集合元素的值传递给了迭代变量,所以修改迭代变量的值不会对集合元素本身有任何影响。

如果在iterator迭代collection集合过程中修改collection集合。程序会在运行时发生异常。

8.2.3 使用Lambda表达式遍历Iterator

forEachRemaining(Consumer action)

8.2.4 使用foreach循环遍历集合元素

for(Object obj:book)

8.2.5 使用java8新增的predicate操作集合

removeIf(predicate filter)把满足predicate的方法留下来

8.2.6使用java新增的Stream操作集合

Stream是一个通用的流接口,

独立使用Stream的步骤:

1.调用Builder()

2.add()

3 调用build()

4.使用聚集方法,大部分聚集方法,每个只能执行一次

Stream提供了大量的方法进行聚类操作

分为:中间方法 末端方法

有状态的方法 短路方法

8.3 Set集合

实际上Set就是Collection ,只是Set不允许包含重复元素。

8.3.1 HashSet类

HashSet是Set接口的典型实现,HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能

特点:

不能保证顺序

不是同步的

集合元素值可以是null

HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也是相等的。

如果多个元素的 hashCode值相同,但是它们通过equals返回false,则需要在一个桶里面保存多个元素,导致性能的下降。

重写hashCode()方法的基本规则

在程序运行过程中,同一个对象多次调用hashCode()返回值相同

当两个对象通过equals()方法返回true时,这两个对象的hashCode()方法返回值相同

对象用作equals()方法比较标准的实例变量,都应该用于计算hashcode值

注意⚠:当程序吧对象添加到hashSet后,尽量不要更改集合元素中参与计算hashCode() equals()的实例变量,否则将导致无法正确操作这些元素。

8.3.2 LinkedHashSet

LinkedHashSet是HashSet的子类,但是总是按照添加的顺序保存对象。但是仍然不能有重复。

8.3.3 TreeSet类

TreeSet类是SortedSet接口的实现类。TreeSet可以确保集合元素处于排序状态。

1.自然排序

调用集合元素的compareTo(Object obj)来比较元素之间的大小关系,然后把集合元素按升序排列。

注意⚠:

试图把一个对象加入TreeSet时,该对象必须实现Comparatable接口,否则程序将抛出异常。

总结一句话:TreeSet如果想正常运行,必须只能添加同一种类型的对象。

TreeSet集合判断两个对象是否相等的唯一标准是:两个对象通过compareTo()方法比较是否返回0。

注意⚠:不要修改TreeSet集合元素的关键实例变量。

2.定制排序

实现定制排序,在创建TreeSet对象时,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责集合元素的排序逻辑。

EnumSet类

EnumSet是专门为枚举类设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值,元素是有序的,EnumSet以枚举值在Enum类内定义顺序来决定集合的顺序,

EnumSet 集合不允许加入null, 且必须用类方法创建。

当试图复制一个Collection集合里的元素来创建EnumSet集合时,必须保证Collection集合里面的所有元素都是同一个枚举类的枚举值。

8.3.5 各Set实现类的性能分析

HashSet性能总是比TreeSet好,

只有当需要一个保持排序的Set时,在应该使用TreeSet'

LinkHashSet遍历起来更加方便,普通的操作不如HashSet

EnumSet性能最好,但是有局限

这三个都是线程不安全的。必须手动同步。

8.4 List集合

List集合代表一个元素有序,可重复的集合。集合中每个元素都有其对应的顺序索引。

8.4.1 java8改进的List接口和ListIterator接口

List集合增加了一些根据索引来操作集合元素的方法。

List判断两个对象相等只要通过equals()方法比较返回true.

set(int index,Object element)方法不会改变List集合的长度。

ListIterator方法来遍历List元素。它增加了向前迭代的功能。hasPrevious() lit.previous()

8.4.2 ArrayList和vector实现类

不要用vector stack

用ArrayList ArrayDeque

8.4.3 固定长度的List

有一个操作数组的工具类Arrays,有一个asList()方法,可以把一个数组或者指定个数的对象转换成list集合,这个集合时Array的内部类ArrayList的实例,时固定长度的List集合。

8.5 Queue集合

Queen用于模拟队列这种数据结构,队列通常是“先进先出”的容器。

8.5.1 PriorityQueen实现类

PriorityQueen是一个比较标准队列实现类,因为保存队列元素的顺序并不是按照加入的顺序,而是按照队列元素的大小重新排列。

注意⚠:不允许插入null元素

8.5.2 Deque接口与ArrayDeque实现类

Deque接口是Queen 接口的子接口,代表一个双短队列

Deque接口提供了一个典型的实现类:ArrayDeque。基于数组实现的双端队列。既可以当栈,也可以当队列。当栈的话,就用push peek pop

当队列的话,就用offer peek poll.

8.5.3 LinkedList实现类

既可以当栈,也可以当队列

8.5.4 各种线性表的性能对比

如果需要遍历集合元素,ArrayList更好,使用随机访问方法(get)来遍历

如果经常执行插入删除,LinkedList更好

如果多个线程同时访问List 集合中元素,考虑使用Collections将集合包装成线程安全

8.6 java8增强的Map集合

Map又叫字典,或者关联数组。

8.6.2 java8改进的HashMap和Hashtable实现类

判断两个key相等的条件:两个key通过equals()比较返回true,并且hatched相等。

判断两个value相等的雕件:通过equals返回true

注意⚠:尽量不要使用可变对象作为hashmap的key,如果做了,也尽量不要改变。

8.6.3 LinkedHashMap实现类

使用双向链表维护key-value的次序,迭代顺序与key-value对的插入顺序一致

8.6.4 使用Properties读写属性文件

可以把map对象和属性文件联系起来,从而把Map 对象中的key-value对写入属性文件,也可以把文件中的key-value加载到map中,key和value都是字符串类型。

8.6.5 SortedMap接口和TreeMap实现类

8.6.6 WeakHashMap实现类

8.6.7 IdentityHashMap

当且仅当两个key严格相等(==),才认为两个key相等。

8.6.8 EnumMap实现类

8.6.9 性能分析

HashMap最常用

8.7 HashSet和HashMap的性能选项

负载极限

8.8 操作集合的工具类:Collections

8.8.1 排序操作

8.8.2 查找替换操作

8.8.3 同步控制

8.8.4 设置不可变集合

8.9 麻烦的接口:Enumeration

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述 有 $n$ 种不同面额的硬币,每种硬币的数量无限。假设硬币面额为 $a_1,a_2,...,a_n$,现在要用这些硬币来找零 $m$ 元,求最少需要的硬币个数。 样例 输入:5,[1,2,5] 输出:2 算法1 (动态规划) $O(nm)$ 很明显,这是一道动态规划的问题。 设 $f[i][j]$ 为只考虑前 $i$ 种硬币,总面值为 $j$ 元时所需的最少硬币数。 显然,对于 $f[i][j]$,我们可以选择不取第 $i$ 种硬币,此时 $f[i][j]=f[i-1][j]$。也可以选择取第 $i$ 种硬币,此时 $f[i][j]=f[i][j-a_i]+1$。 于是,状态转移方程为: $$f[i][j]=\min(f[i-1][j],f[i][j-a_i]+1)$$ 注意,当 $j<a_i$ 时,显然不能取第 $i$ 种硬币,因此 $f[i][j]=f[i-1][j]$。 最终答案即为 $f[n][m]$。 时间复杂度 状态数为 $nm$,转移复杂度为 $O(1)$,故总时间复杂度为 $O(nm)$。 参考文献 无 C++ 代码 class Solution { public: int coinChange(vector<int>& coins, int amount) { int n = coins.size(); vector<vector<int>> f(n+1,vector<int>(amount+1,0x3f3f3f3f)); for(int i=0;i<=n;++i) f[i][0] = 0; for(int i=1;i<=n;++i){ for(int j=1;j<=amount;++j){ if(j<coins[i-1]) f[i][j] = f[i-1][j]; else f[i][j] = min(f[i-1][j],f[i][j-coins[i-1]]+1); } } return f[n][amount]>=0x3f3f3f3f?-1:f[n][amount]; } }; Java 代码 class Solution { public int coinChange(int[] coins, int amount) { int n = coins.length; int[][] f = new int[n+1][amount+1]; for(int i=0;i<=n;++i) f[i][0] = 0; for(int i=1;i<=n;++i){ for(int j=1;j<=amount;++j){ if(j<coins[i-1]) f[i][j] = f[i-1][j]; else f[i][j] = Math.min(f[i-1][j],f[i][j-coins[i-1]]+1); } } return f[n][amount]>=0x3f3f3f3f?-1:f[n][amount]; } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值