目录
什么是集合?
-
集合是一种新容器,集合可以存储数量不固定的元素(数组的空间是固定的,你申请多少空间以后都不能改变),而集合可以动态的增加空间(有些是空间不够时新建一个足够大的数组再把原来的元素移到新的数组中)。
-
集合的出现解决的几个问题:
- 存储数量不等的元素。
- 定义了数据结构,所以集合的元素可以依据数据结构来读取,比如LinkList(可以理解成链表结构的数组),HashSet(哈希表结构)
- 可以存储具有映射关系的元素(Map)
-
集合中存储的元素都是对象(默认取出的也是一个Object对象),即使存入的是一个数字,也会转换成 Integer 类。
-
集合存放的只是对象的引用
-
java中集合类体系主要分为两类:主要用于存储普通元素的Collection、用于存储具有映射关系的元素的Map。
集合体系图
Collection集合
介绍:Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。
所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。
Collection集合接口包含两个实现子接口,分别是List和Set。
List包括ArrayList和LinkedList两个具体实现类。
Set包括HashSet这个具体实现类。
方法:
- 添加元素:
- 添加一个元素X:add(X)
- 添加集合X中全部元素到集合中:addAll(X)
- 删除元素:
- clear():移除此 collection 中的所有元素
- remove(x):移除指定元素x
- removeAll(x):移除集合中另一个集合x的元素
- 检查:
- size():检测集合的元素个数
- isEmpty():检测集合是否为空,空返回true
- contains(x):是否包含某元素x
- containsAll(x):是否包含另一个集合x中的所有元素。
- 其他:
- toArray():将集合转成数组
- iterator():返回可以在此集合上进行元素迭代的迭代器
- equals(x):比较集合是否与x一致。
集合的获取依赖于迭代器Iterator。
###1.Collection集合的成员方法:
* boolean add(E e):添加元素
* boolean remove(Object o):从集合中移除元素
* void clear():清空集合中的元素
* boolean contains(Object o):判断集合中是否存在指定的元素
* boolean isEmpty():判断集合是否为空
* int size():集合的长度,也就是集合中元素的个数
###2.Collection集合的遍历:
* Iterator<E> iterator():
* 返回在此 collection 的元素上进行迭代的迭代器。
* 通过集合对象调用iterator()方法得到迭代器对象。
*
* Iterator:
* E next():返回迭代的下一个元素。
* boolean hasNext():如果仍有元素可以迭代,则返回 true。
List集合
List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。
和下面要提到的Set不同,List允许有相同的元素。
除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。
实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。
1.List集合的特有成员方法(除了Collection中有的方法):
* void add(int index,E element):在指定位置添加元素,原位置上的元素后移
* E remove(int index):删除指定位置的元素,返回删除的元素
* E get(int index):获取指定位置的元素
* E set(int index,E element):修改指定位置的元素,返回修改前的元素
2.List集合的遍历:
//迭代器
Iterator<Student> it = list.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+"---"+s.getAge());
}
//普通for
for(int x=0; x<list.size(); x++) {
Student s = list.get(x);
System.out.println(s.getName()+"---"+s.getAge());
}
3.List集合子类特点及ArrayList集合:
ArrayList:底层数据结构是数组,查询快,增删慢
LinkedList:底层数据结构是链表,查询慢,增删快
ArrayList遍历:
//迭代器
Iterator<String> it = array.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
//普通for
for(int x=0; x<array.size(); x++) {
String s = array.get(x);
System.out.println(s);
}
//增强for
for(String s : array) {
System.out.println(s);
}
提示:LinkedList的使用和ArrayList的相似,所以LinkedList的具体构造方法和成员方法可以去API文档查看。
Set集合
Set集合的特点:
Set集合只有HashSet一个具体实现类
Set:一个不包含重复元素的 collection
-----元素唯一,存储元素无序
##常用实现类
1.HashSet:
- 哈希表结构的集合
- 利用哈希表结果构成的集合查找速度会很快。
- 它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
- HashSet实现了Set集合接口。
HashSet保证元素唯一性的原理???
通过查看add方法的源码,我们知道了添加功能的执行过程中,是进行了数据的判断的。
这个判断的流程是:
首先比较对象的哈希值是否相同,这个哈希值是根据对象的hashCode()计算出来的。
如果哈希值不同,就直接添加到集合中
如果哈希值相同,继续执行equals()进行比较,
返回的是true,说明元素重复,不添加。
返回的是false,说明元素不重复,就添加。
如果我们使用HashSet集合存储对象,你要想保证元素的唯一性,就必须重写hashCode()和equals()方法。
###HashSet集合的遍历:
//迭代器
Iterator<Student> it = hs.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+"---"+s.getAge());
}
//增强for
for(Student s : hs) {
System.out.println(s.getName()+"---"+s.getAge());
}
2.TreeSet:
- 二叉树结构的集合
- 二叉树插入元素是有顺序的,TreeSet的元素是有序的。
- 由于二叉树需要对结点排序(插入的结点位置),默认情况下没有排序方法,所以元素需要继承Comparator并重写compareTo方法来实现元素之间比较大小的功能。
- 对于TreeSet,compareTo方法来保证元素的唯一性。【这时候可以不重写equals】
3.LinkHashSet:
是HashSet的子类,是链表跟哈希表的数据结构的结合,上一个元素会存储下一个元素的位置,所以可以按顺序来取出。
LinkedHashSet lhs = new LinkedHashSet();
lhs.add("a");
lhs.add("d");
lhs.add("c");
lhs.add("b");
System.out.println(lhs);//运行结果:[a, d, c, b]
Map集合
介绍Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。
1.Map集合的成员方法
V put(K key,V value):添加元素
V remove(Object key):根据键删除键值对元素
void clear():移除所有的键值对元素
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
int size():返回集合中的键值对的对数
2.Map集合的获取功能测试
V get(Object key):根据键获取值
Set<K> keySet():获取所有键的集合
Collection<V> values():获取所有值的集合
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("书", "平凡的世界");
map.put("水果", "苹果");
map.put("车子", "劳斯莱斯");
//V get(Object key):根据键获取值
System.out.println("get:"+map.get("车子"));
System.out.println("get:"+map.get("肉"));
System.out.println("--------------------");
//Set<K> keySet():获取所有键的集合
Set<String> set = map.keySet();
for(String key : set) {
System.out.println(key);
}
System.out.println("--------------------");
//Collection<V> values():获取所有值的集合
Collection<String> values = map.values();
for(String value : values) {
System.out.println(value);
}
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dTjOYEbB-1598158958414)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200823124616691.png)]
3.Map集合的遍历之键找值
A:获取所有键的集合
B:遍历键的集合,获取到每一个键
C:根据键去找值
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("书", "平凡的世界");
map.put("水果", "苹果");
map.put("车子", "劳斯莱斯");
//获取所有键的集合
Set<String> set = map.keySet();
//遍历键的集合,获取到每一个键
for(String key : set) {
//根据键去找值
String value = map.get(key);
System.out.println(key+"---"+value);
}
4.Map集合的遍历之键值对对象找键和值
A:获取所有键值对对象的集合
B:遍历键值对对象的集合,得到每一个键值对对象
C:根据键值对对象获取键和值
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("书", "平凡的世界");
map.put("水果", "苹果");
map.put("车子", "劳斯莱斯");
//获取所有键值对对象的集合
//Set<Map.Entry<K,V>> entrySet()
//获取键值对对象的集合
Set<Map.Entry<String,String>> set = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for(Map.Entry<String,String> me : set) {
//根据键值对对象获取键和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key+"---"+value);
}
实例展示:
ArrayList:
import java.awt.*;
import java.util.*;
public class CollectionTest
{//List是一个能包含重复元素的已排序的Collection,有时list也称为序列,List第一个元素的下标为0
public String colors[]={"red","white","blue"};//定义一个字符数组
//构造函数
public CollectionTest()
{
ArrayList list=new ArrayList();//实例化一个ArrayList
list.add(Color.magenta);//向里面添加一个元素,这里是颜色
for(int count=0;count<colors.length;count++)
list.add(colors[count]);//加入开始声明的数组中的元素
list.add(Color.cyan); //颜色 导入awt包
System.out.println("\nArrayList");
for(int count=0;count<list.size();count++)
System.out.println(list.get(count)+" ");//从arrayList中读取 元素
removeString(list);
System.out.println("\n\nArrayList after calling"+"removeString:");
for(int count=0;count<list.size();count++)
System.out.println(list.get(count)+" ");
}
public void removeString(Collection collection)
{
Iterator itrator=collection.iterator(); //声明一个迭代
//调用itrator的hasNext方法判断Collection是否还包含元素
while(itrator.hasNext())
{
//调用itrator的next方法获得下一个元素的引用
if( itrator.next() instanceof String ) // instanceof 判断是否是String 的实例
itrator.remove(); //如果是的 则删除
}
}
public static void main(String[] args)
{
new CollectionTest();
}
}
该例示范了ArrayList的使用 先声明了一String类型的数组,里面存储了“颜色”,是用字符串写出的颜色,将这个字符串数组存入ArrayList实例,同时还存入了awt包内的颜色实例,全部存入后利用迭代,删除不符要求的假数据,也就是我们用字符串写的颜色,也用到了 instanceof 它是一个二元操作符,类似于equals用于判断instanceof左边 的对象 是否是 右边对象的实例,若是 返回真,这里就可以判断 ArrayList里面的真假颜色,假颜色是 字符串的 实例,所以我们通过迭代 一个个对比。只要是String的实例就将其从数组中删除,所以最后 ArrayList里面仅仅剩下二个元素,运行效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0E8tpbVP-1598158958416)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200823121158991.png)]
HashSet:
//Set是包含独一无二元素的Collection,HashSet把它的元素存储在哈希表中,而TreeSet把它的元素存储在树中
import java.util.*;
public class SetTest
{
private String colors[]={"orange","tan","orange","white", "gray"};
public SetTest()
{
ArrayList list;
list=new ArrayList(Arrays.asList(colors));
System.out.println("ArrayList:"+list);
printNonDuplicates(list);
}
public void printNonDuplicates(Collection collection)
{
//构造HashSet删除Collection中多余的元素
HashSet set=new HashSet(collection);
// 将coolection放入HashSet后即会消除重复元素
System.out.println("set:"+set);
Iterator itrator=set.iterator();
System.out.println("\nNonDuplicates are:");
while(itrator.hasNext())
System.out.println(itrator.next()+" ");
System.out.println();
}
public static void main(String[] args)
{
new SetTest();
}
}
运行如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eoqIRi20-1598158958422)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200823125630910.png)]
总结:
Connection接口:
— List 有序,可重复
- ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高 - Vector
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程安全,效率低 - LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
—Set 无序,唯一
- HashSet
底层数据结构是哈希表。(无序,唯一)
如何来保证元素唯一性?
1.依赖两个方法:hashCode()和equals() - LinkedHashSet
底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1.由链表保证元素有序
2.由哈希表保证元素唯一 - TreeSet
底层数据结构是红黑树。(唯一,有序)
\1. 如何保证元素排序的呢?
自然排序
比较器排序
2.如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
Map接口:
Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable。
- TreeMap是有序的,HashMap和HashTable是无序的。
- Hashtable的方法是同步的,HashMap的方法不是同步的。这是两者最主要的区别。
这就意味着:
-
Hashtable是线程安全的,HashMap不是线程安全的。
-
HashMap效率较高,Hashtable效率较低。
如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。 -
Hashtable不允许null值,HashMap允许null值(key和value都允许)
-
父类不同:Hashtable的父类是Dictionary,HashMap的父类是AbstractMap
400/fill/I0JBQkFCMA==/dissolve/70)
Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable。
- TreeMap是有序的,HashMap和HashTable是无序的。
- Hashtable的方法是同步的,HashMap的方法不是同步的。这是两者最主要的区别。
这就意味着:
-
Hashtable是线程安全的,HashMap不是线程安全的。
-
HashMap效率较高,Hashtable效率较低。
如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。 -
Hashtable不允许null值,HashMap允许null值(key和value都允许)
-
父类不同:Hashtable的父类是Dictionary,HashMap的父类是AbstractMap
以上内容综合了多篇文章,希望大家好好学习,天天向上!