Java集合类初探
-
集合概述
初学Java,我比较好奇Java有没有类似于像Python的列表,元组,集合这种序列来处理数据的方式,毕竟从C语言到Python的学习,让我体会到了Python之余"简单"的"先进",随着逐步的学习深入,我体会到Java中的集合是一个类似于我上述这样的序列,但是在灵活程度上Java还是不及Python,毕竟各种语言有各种语言的风格吧。
首先声明一点:集合中可以储存不同的数据类型,其实本质上,集合用来存放对象的引用
常用的集合有 List集合,Set集合,Map集合,其中 List集合 和 Set集合 继承了 Collection接口,各接口还提供了不同的实现类。
上述集合类的继承关系图如下:
· Collection接口的常用方法,在各种类型的集合中都能用
方 法 功能描述 set.add(e) 将对象e添加到该集合set中 set.remove(e) 将指定的对象e从集合set中移除 set.isEmpty() 用于判断当前集合是否为空,返回类型为boolean set.iterator() 生成迭代器,用于遍历集合中的对象 set.size() 获取该集合中元素的个数,返回值为int型
-
List集合
List集合包括List接口以及List接口的所有实现类。List集合中的元素允许被重复,各元素的顺序就是对象插入时候的顺序。
List接口继承了Collection接口,因此包含Collection接口中的所有方法。此外,List接口还定义了以下两个非常重要的方法:
list.get(int index) 获得指定索引位置的元素 list.set(int index,Object obj) 将集合中指定索引位置的对象修改为指定的对象
List接口的实现类
①ArrayList
②LinkedList
- 来看一下它们的区别:
ArrayList | LinkedList |
---|---|
ArrayList在内部使用动态数组存储元素。 | LinkedList在内部使用双向链表来存储元素。 |
使用ArrayList增删操作很慢,因为它的内部使用数组。如果从ArrayList中删除了任何元素,则所有位都将在内存中移位。 | 使用LinkedList增删操作比ArrayList更快,因为它使用了双向链接列表,因此不需要在内存中进行任何移位。 |
ArrayList类只能用作列表,因为它仅实现List。 | LinkedList类可以实现列表和队列,因为它实现了List和Deque接口。 |
ArrayList 更适合存储和访问数据。 | LinkedList 更适合处理数据。 |
#¥%接下来讲解一下List常用的方法,适用于Arraylist和LinkedList
一、如何创建一个Arraylist对象
Arraylist<Object> list = new Arraylist<>();
//这里的Object可以指定任何类型,如果类型不同,就直接写Object即可
二、向List集合中添加元素
- add(s)方法
list.add("China");
list.add("Amercia");
System.out.println(list);
输出结果:
[China,Amercia]
加强版本的add方法:
- add(int index,Object object)
向指定位置添加元素 object,原位置的元素向后移
三、获取指定位置的元素
- get()方法
list.get(0)
输出结果:
China
四、替换或设置指定位置的元素
- set(int i,Object ob)
- 过于简单不举例子了_
五、清空集合
- clear()方法
- 清空list集合中的所有元素
六、判断集合是否为空
- isEmpty()方法 返回类型为boolean
七、判断集合中是否有特定元素
- contains(s)方法 返回类型为boolean
八、删除元素
- ①删除指定位置的元素:remove(int i)方法,删除指定位置的元素,并将此元素返回
- ②删除某个特定元素:remove(object)方法, 删除成功返回true,否则返回false
九、当然上面说的Collection接口中的方法也全能用啊!
-
Set集合
首先说明一点,Set集合不同于List集合的一点是Set集合不能有重复的元素
由上面的图我们知道,Set接口常用的实现类有 HashSet类与TreeSet类
Set中元素不可以重复,是无序的(这里的无序是指存入元素的先后顺序与输出元素的先后顺序不一致)
- 接下来是特别无聊的它们的区别部分
HashSet:
①内部的数据结构是哈希表,是线程不安全的。
②HashSet中保证集合中元素是唯一的方法:通过对象的hashCode和equals方法来完成对象唯一性的判断。如果对象的hashCode值不同**,则不用判断equals方法,就直接存到HashSet中。**
注意:如果元素要存到HashSet中,必须覆盖hashCode方法和equals方法。
③HashSet是哈希表实现的,HashSet中的元素是无序的。集合元素可以是null,但只能放入一个null。
HashSet要求放入的对象必须实现HashCode()方法,放入的对象是以hashcode码作为标识的,而具有相同内容的String对象,HashCode是一样的,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例。
TreeSet:
TreeSet是SortedSet接口的唯一实现类,TreeSet可以保证集合元素处于排序状态。TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序是默认的排序方式,想TreeSet中加入的对象应该是同一个类的对象。
①可以对Set集合中的元素进行排序,是线程不安全的。
②TreeSet判断元素唯一性的方法是:根据比较方法的返回结果是否为0,如果是0,则是相同元素,如果不是0,是不同元素,存储。
③TreeSet对元素进行排序的方式:元素自身具备比较的功能,即自然排序,需要实现Comparable接口,并覆盖其compareTo方法。元素本身不具备比较功能的,则需要实现Comparator,并覆盖其compare方法(定制排序)。
④TreeSet是二叉树实现的,TreeSet中的数据是自动排好顺序的,不允许放入null值
总结:HashSet存放对象的时候判断对象是否相等,是根据对象的hashCode和equals方法。TreeSet存放对象时,是根据对象的compareTo方法比较两个对象是否相等,并进行比较。
Hashset和Treeset的使用场景
HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定的顺序来存放。
TreeSet:提供一个使用树结构存储set接口的实现(红黑树算法)。对象以升序顺序存储,访问和遍历的时间很快。
使用场景:HashSet是基于Hash算法实现的,其性能通常都优于TreeSet。我们通常都应该使用HashSet,在我们需要排序的功能时,我们才使用TreeSet。
ps:以上这段文字转载自 (点击这里)
#¥%接下来讲解一下Set常用的方法
一、添加元素
- add(e)方法,就是Collection接口中的方法,不作过多赘述
- addAll(Collection A)方法,把集合A中的元素全部添加到本集合里边
二、清空集合
- void clear()方法
三、检测是否包含
- boolean contains(Object o)方法, 检测集合中是否包含o对象
- boolean contains (Collection A)方法, 检测集合中是否包含A集合中的所有对象
四、比较集合是否相等,即比较里面的元素是否相等,而不是比较地址
在Object类中,equals()方法底层就是“==”,也就是说就是比较地址是否相等,但是继承后,大多数的类都重写了该方法
- equals(Object o)方法
五、返回集合的哈希码值
-
int hashCode()方法
ps:目前我还不知道这个方法有什么具体作用。
六、判断集合是否为空
- boolean isEmpty()方法
七、删除集合中的元素
- boolean remove(Object o) 从指定集合中删除 o ,如果有这个元素,并且删除诚通就返回true,否则返回false
- boolean removeAll(Collection A)从指定集合中删除A集合中的所有元素,注意只要是Collection接口下的集合都可以
八、保留元素
- boolean retainAll(Collection A)仅仅保留A集合中的所有元素
九、toArray()方法
将一个集合转为数组
HashSet<Object> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Water");
Object[] ob = set.toArray(); //将集合以数组形式赋值给ob
for (Object o : ob) {
System.out.println(o);
}
输出结果如下:
Water
Apple
Banana
到这里基于Collection接口的实现类就基本介绍完了,最后再提一下如何遍历输出这些集合中的元素
具体看下面代码
- 方法一:
ArrayList<Object> list = new ArrayList<>();
list.add("China");
list.add("Amercia");
list.add("France");
Iterator<Object> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
- 方法二:(注意该方法只试用于List接口,因为set接口下没有get()方法)
ArrayList<Object> list = new ArrayList<>();
list.add("China");
list.add("Amercia");
list.add("France");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
方法 | 功能描述 |
---|---|
put(key,value) | 向指定集合添加key 与 value 的映射关系,其实就是添加键值对 |
putAll(Map) | 把一个map集合合并到另一个map集合 |
containsKey(Object key) | 如果此集合包含key的映射关系,就返回true |
containsValue(Object value) | 如果此映射将一个或多个key映射到指定值,则返回true |
get(key) | 如果存在指定的key对象,则返回该对象的值,否则返回null |
keyset() | 返回该集合中所有的key对象形成的Set集合 |
values() | 返回该集合中所有值对象形成的Collection集合 |
size() | 返回该集合中键值对的个数 |
remove(key) | 移除该集合中键为key的键值对 |
clear() | 清除集合中所有的键值对 |