Java与Kotlin的类集

本文2个方向

  1. Java类集的介绍以及代码分析
  2. Kotlin中类集的使用以及相关优化

Java类集的介绍以及代码分析

  1. 找到Collection接口
  2. Collection接口有什么
  3. 整个类集框架的结构是什么
  4. List接口是什么样的 ArrayList LinkedList怎么使用
  5. Set接口是什么样 HashSet TreeSet SortedSet怎么使用
  6. Map<K,V>接口是什么样 HashMap TreeMap怎么使用
  7. 迭代器是什么,怎么使用

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 HashMapSet HashSetList 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部分:

  1. Collection集合,存储一个元素集合;
  2. 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个部分组成:

  1. 接口 代表抽象的数据类型,例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
  2. 实现 接口的具体实现,可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap
  3. 算法 实现类中的一些计算,例如搜索和排序

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()删除当前元素
复制代码

迭代的流程是什么呢:

  1. 取得迭代方法Iterator iterator();
  2. 建立一个调用hasNext()方法的循环,只要返回true就进行循环迭代
  3. 在循环内部,通过调用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,他们之间存在以下几个异同点:

  1. 它们都是接口,并不是实际的类。
  2. 它们只实现了isEmpty()、size、contains()等函数以及属性。
  3. List和Set都继承至Collection接口,且Collection继承于Iterable接口。 而Map<K,V>是独立出来的一个接口。这一点和Java相同。
  4. 这三种集合类型分别有存在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)
}
复制代码

猜你喜欢

转载自juejin.im/post/5ec10b5be51d454daa7422bc