本文2个方向
- Java类集的介绍以及代码分析
- Kotlin中类集的使用以及相关优化
Java类集的介绍以及代码分析
- 找到Collection接口
- Collection接口有什么
- 整个类集框架的结构是什么
- List接口是什么样的 ArrayList LinkedList怎么使用
- Set接口是什么样 HashSet TreeSet SortedSet怎么使用
- Map<K,V>接口是什么样 HashMap TreeMap怎么使用
- 迭代器是什么,怎么使用
1.找到Collection接口
先看下面的代码
//键值对
Map map = new HashMap();
map.put("name","hong");
//不可重复的数组
Set set = new HashSet();
set.add("hong");
//可重复数组
List<String> list = new ArrayList<>();
list.add("hong");
复制代码
上面创建了3种不同的集合类,键值对,不可重复数组以及可重复数组。发现一个规律是左右2边不同 Map
HashMap
、Set
HashSet
、List
ArrayList
那么可以看看左边究竟是什么:
Map的结构
public interface Map<K,V> 是一个接口 其中定义了各种方法
Set的结构
public interface Set<E> extends Collection<E>
List的结构
public interface List<E> extends Collection<E>
public interface Collection<E> extends Iterable<E>
复制代码
那么这个类集的父接口就找到了就是Collection<E>
,所有类集的核心方法都在里面了
2.Collection接口有什么
我们来看看这个接口里提供了什么方法:
int size(); 返回调用集合中元素的个数
boolean isEmpty(); 如果调用集合是空的就返回true否则返回false
boolean contains(Object o); 如果obj是调用集合的一个元素,就返回true,否则返回false
Iterator<E> iterator();返回调用集合的迭代器
Object[] toArray();返回一个数组,这个数组包含了所有储存在这个调用集合中的元素,作为一个备份
<T> T[] toArray(T[] a);返回一个数组,该数组仅仅包含了那些类型与数组元素类型匹配的类集元素。
boolean add(E e); 将E类型的数据添加到集合中,返回true,如果不允许有重复的元素且包含了e就返回false
boolean remove(Object o);从调用集合中删除o,如果被删除了就返回true否则返回false
boolean containsAll(Collection<?> c);如果调用集合中包含了c中的所有元素就返回true否则返回false
boolean addAll(Collection<? extends E> c);将c中的元素都加入到调用类集中,如果操作成功了就返回true否则false
boolean removeAll(Collection<?> c); 从调用集合中删除c中所有元素
boolean retainAll(Collection<?> c); 删除调用集合中除了包含在c中的元素之外的全部元素,如果类集被改变了就返回true
void clear();从调用类集中删除所有元素
boolean equals(Object o);如果调用集合和o相等就返回true
int hashCode();返回调用集合的hash值
复制代码
对于这个接口,它是不会被直接使用的,而是被其子接口使用像:list / set
3.整个类集框架的结构是什么
从上图分析,集合框架分为2部分:- Collection集合,存储一个元素集合;
- Map图,存储键值对 Collection 接口又有 3 种子类型,List、Set 和 Queue, 再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、HashMap、LinkedHashMap 等等
知道了整个集合框架的继承关系后,我们来研究下,实现一个集合类要哪些部分呢? 我们从他们的子接口出发去探究下。
4. List接口是什么样的 ArrayList LinkedList怎么使用
List接口与Collection接口的不同点
增加方法:
void add(int index, E element); 将element插入到调用列表钟,插入位置的下标由index传递。任何已存在的,在插入点以及插入点之后的元素都将后移。没有元素会被覆盖
boolean addAll(int index, Collection<? extends E> c);将c中的所有元素插入到调用列表中,插入位置的下标由index传递
E remove(int index);删除调用列表中index位置的元素并返回删除的元素。删除,被删除元素后面的元素下标减1
int indexOf(Object o); 返回调用列表中o第一次出现的下标,如果不是列表中的元素就返回-1
int lastIndexOf(Object o);返回调用列表中obj最后一次出现的下标
E get(int index); 返回存储在调用类集内指定下边的对象
E set(int index, E element);用element对调用列表内由index之指定的位置进行赋值
List<E> subList(int fromIndex, int toIndex);返回一个列表,该表包括了调用列表中从start到end-1的元素。
特性:使用一个基于0的下标,元素可以通过他们在列表中的位置被插入和访问
复制代码
5. Set接口是什么样 HashSet TreeSet SortedSet怎么使用
Set<E>接口与Collection接口的不同点
增加方法:没有,完全集成了Collection接口
特性:类集中元素不允许重复,即在set中不能出现完全相同的2个元素。
复制代码
6. Map<K,V>接口是什么样 HashMap TreeMap怎么使用
Map<K,V>接口
int size();返回映射中关键字/值对的个数
boolean isEmpty();如果调用映射是空的,则返回true
boolean containsKey(Object key);如果调用映射中包含了作为关键字的k,则返回true
boolean containsValue(Object value);如果映射中包含了作为值的v,则返回true
V get(Object key);返回与关键字k相关联的值
V put(K key, V value);将一个输入加入调用映射,改写原先与该关键字相关联的值。
V remove(Object key);删除关键字等于k的输入
void putAll(Map<? extends K, ? extends V> m);将所有来自m的输入加入到调用映射
void clear();从调用映射中删除所有的关键字/值对
Set<K> keySet();返回一个包含调用映射中关键字的集合。
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();将Map集合变为Set集合返回
boolean equals(Object o);如果o是一个Map并包含相同的输入,则返回true
int hashCode();返回调用映射的散列码
interface Entry<K,V> 描述映射中的元素(关键字、值对)
K getKey();返回该映射项的关键字
V getValue();返回该映射项的值
V setValue(V value);将这个映射输入的值赋给v
boolean equals(Object o);如果o是一个关键字的值都与调用对象相等的Map.Entry则返回true
int hashCode();返回该映射项的散列值
特性:存储键值对,key不可重复而value可以
复制代码
通过上面接口以及各个实现的观察发现,一个集合类有3个部分组成:
- 接口 代表抽象的数据类型,例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
- 实现 接口的具体实现,可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap
- 算法 实现类中的一些计算,例如搜索和排序
7.迭代器是什么,怎么使用
对于数组,可以使用如下方法进行遍历:
List<String> names = new ArrayList<>();
names.add("赵");
names.add("钱");
names.add("孙");
names.add("李");
System.out.println("方式一");
//for循环依据索引来遍历对象,所以在随机访问中比较快(比如ArrayList)
for (int i = 0; i < names.size() ; i++) {
System.out.println(names.get(i));
}
System.out.println("方式一");
for (String name:names) {
System.out.println(name);
}
System.out.println("方式三");
//迭代器的next()采用的是顺序访问方法,所以在顺序访问的集合中速度更快(比如LinkedList)
Iterator iterator = names.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
复制代码
使用迭代器是怎么样的呢
System.out.println("方式三");
//迭代器的next()采用的是顺序访问方法,所以在顺序访问的集合中速度更快(比如LinkedList)
Iterator iterator = names.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
Map map = new HashMap<String,Integer>();
map.put("赵",22);
map.put("钱",33);
map.put("孙",10);
map.put("李",40);
Iterator iterator2 = map.entrySet().iterator();
while (iterator2.hasNext()){
Map.Entry entry = (Map.Entry) iterator2.next();
System.out.println("Key : "+entry.getKey());
System.out.println("Value : "+entry.getValue());
}
复制代码
那么迭代器是什么呢,先看其接口
public interface Collection<E> extends Iterable<E>
表示实现了Collection接口的类都是可迭代的
Iterable<E>迭代器接口有
Iterator<T> iterator();
default void forEach(Consumer<? super T> action)
default Spliterator<T> spliterator()
Iterator
boolean hasNext(); 判断是否有下一个元素,如果存在更多元素就返回true
E next();取得下一个元素
default void remove()删除当前元素
复制代码
迭代的流程是什么呢:
- 取得迭代方法Iterator iterator();
- 建立一个调用hasNext()方法的循环,只要返回true就进行循环迭代
- 在循环内部,通过调用next()方法获取每一个元素
Kotlin中类集的使用以及相关优化
kotlin是在java的基础上进行修改的,主要是增加了不可变集合类。 创建方式如下
//不可变数组/键值对 只读
var list = listOf<String>("赵","钱","孙","李")
var map = mapOf<String,Int>("赵" to 22,"钱" to 33,"孙" to 40,"李" to 55)
var set = setOf<String>("赵","钱","孙","李")
//set.add() 无法添加
//set.remove() 没有删除方法
//可变数组/键值对 可变
val mutableList = mutableListOf<String>("赵","钱","孙","李")
val mutableMap = mutableMapOf<String,Int>("赵" to 22,"钱" to 33,"孙" to 40,"李" to 55)
val mutabSet = mutableSetOf<String>("赵","钱","孙","李")
mutabSet.add("111")
复制代码
在Kotlin中,集合类型包含三种类型:它们分别是:List、Set、Map,他们之间存在以下几个异同点:
- 它们都是接口,并不是实际的类。
- 它们只实现了isEmpty()、size、contains()等函数以及属性。
- List和Set都继承至Collection接口,且Collection继承于Iterable接口。 而Map<K,V>是独立出来的一个接口。这一点和Java相同。
- 这三种集合类型分别有存在MutableList、MutableSet、MutableMap<K,V>接口,这些接口中提供了改变、操作集合的方法。例如add()、clear()、remove()等函数。
集合层级关系是:
map和flatmap方法map():遍历每一个元素
flatMap() :遍历每一个元素,并铺平元素 降维
println("map")
val maps = listOf(listOf(1,2), listOf(2,4), listOf(3,6), listOf(4,8))
maps.map {
it.map {
it * 100
}
}.forEach {
println(it)
}
println("flatMap")
maps.flatMap {
it.map {
it * 100
}
}.forEach {
println(it)
}
复制代码
map
[100, 200]
[200, 400]
[300, 600]
[400, 800]
flatMap
100
200
200
400
300
600
400
800
复制代码
如何遍历 :
list.forEach {
println(it)
}
list.forEachIndexed{ index, s ->
println("$s in $index")
}
map.forEach { (key, value) ->
println("key : $key , value : $value")
}
set.forEach {
println(it)
}
复制代码
过滤函数
filter{...} : 把不满足条件的元素过滤掉
filterIndexed{...} : 和filter{}函数作用类似,只是可以操作集合中元素的下标(index)
val list = listOf(22,13,44,55,66,88,102)
//过滤函数 无index
list.filter {
it > 40
}.forEach {
println(it)
}
println("filterIndexed")
//过滤函数 有index
list.filterIndexed { index, i ->
index == 2
}.forEach {
println(it)
}
复制代码
排序函数
reversed() : 反序。即和初始化的顺序反过来。
sorted() : 自然升序。
sortedBy{} : 根据条件升序,即把不满足条件的放在前面,满足条件的放在后面
println("reversed")
//反向排序
list.reversed().forEach {
println(it)
}
println("sorted")
//升序
list.sorted().forEach {
println(it)
}
println("sortedBy")
//有条件升序
list.sortedBy {
it > 50
}.forEach {
println(it)
}
复制代码
去重函数
distinctBy() : 去重
println("distinctBy")
val list1 = listOf(22,22,13,44,44,55,55,66,67,88,102)
list1.distinctBy {
"name$it"
}.forEach {
println(it)
}
复制代码