一、集合
概念:
Java集合大致可分为List、Set、Queue和Map四种体系.
List:代表有序、重复的集合。
Set:代表无序、不可重复的集合。
Map:则代表具有映射关系的集合。
Queue:Java5又增加了Queue体系集合,代表一种队列集合实现。
分类:
Java的集合类主要由两个接口派生而出: Collection和Map, Collection和Map是Java 集合框架的根接口,这两个接口又包含了一些子接口或实现类。如下所示是 Java集合 简单结构图:
二、Collection集合
1、Collection集合
数组的长度是固定的。集合的长度是可变的。
数组存储任意类型数据。集合存储的都是引用数据类型。基本类型需要转为对应的包装类。
2、单列集合:collection;双列集合:map
3、collection中的功能:
public boolean add(E e) : | 把给定的对象添加到当前集合中 。 |
---|---|
public void clear() : | 清空集合中所有的元素。 |
public boolean remove(E e) : | 把给定的对象在当前集合中删除。 |
public boolean contains(Object obj) : | 判断当前集合中是否包含给定的对象。 |
public boolean isEmpty() : | 判断当前集合是否为空。 |
public int size() : | 返回集合中元素的个数。 |
public Object[] toArray() : | 把集合中的元素,存储到数组中 |
4、Iterator迭代器
public Iterator iterator() : 获取集合对应的迭代器,用来遍历集合中的元素的;
public E next() :返回迭代的下一个元素。
public boolean hasNext() :如果仍有元素可以迭代,则返回 true;
实现代码:
Iterator<String> it = coll.iterator();
// 泛型指的是 迭代出 元素的数据类型
while(it.hasNext()){ //判断是否有迭代元素
String s = it.next();//获取迭代出的元素
System.out.println(s);
}
5、增强for:
高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作。
//使用增强for遍历数组
for (int a : arr) {//a代表数组中的每个元素
System.out.println(a);
}
6、泛型:
6.1、含有泛型的类
————含有 泛型的类:——在创建对象的时候确定泛型;
class ArrayList<E> {
public boolean add(E e) {
}
public E get(int index) {
}
}
(1)、创建对象时候确定泛型:
ArrayList<String> list = new ArrayList<String>();
则原来内部代码理解为:
class ArrayList<String> {
public boolean add(String e) {
}
public String get(int index) {
}
}
6.2、含有泛型的方法
————含有含有泛型的方法——调用方法时,确定泛型的类型
public class MyGenericMethod {
public <MVP> void show(MVP mvp) {
System.out.println(mvp.getClass());
}
}
(2)、调用方法时候确定:
public class GenericMethodDemo {
public static void main(String[] args) {
// 创建对象
MyGenericMethod mm = new MyGenericMethod();
// 演示看方法提示
mm.show("aaa");
mm.show(123);
}
}
6.3、含有泛型的方法
————含有泛型的接口——
public interface MyGenericInterface<E> {
public abstract void add(E e);
public abstract E getE();
}
《1》定义类时确定泛型的类型
public class MyImp1 implements MyGenericInterface<String> {
}
@Override
public void add (String e){
}
《2》始终不确定泛型的类型,直到创建对象时,确定泛型的类型
public class MyImp2<E> implements MyGenericInterface<E> {
@Override
public void add(E e) {
}
}
7、泛型通配符:用来匹配泛型的
?: 代表任意的数据类型
注意: 用来匹配泛型的,而不能用来定义泛型
ArrayList<String> list1 = new ArrayList<>();
list1.add("aaa");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(200);
print(list1);
print(list2);
//定义一个方法,完成上面的两个集合的遍历
public static void print (ArrayList < ? > list){
for (Object obj : list) {
System.out.println(obj);
}
}
泛型的注意事项:
《1》创建集合对象时,<>中指定的类型,左右必须保持一致(泛型不存在多态)
《2》ArrayList<?> list:
可以接收ArrayList的任意泛型对象(创建ArrayList集合时,只要<>中定了具体的类型,就是ok的)
ArrayList<?> list;//只是用来接收创建的值得。可以用通配符;
list = new ArrayList<String>();
list = new ArrayList<Integer>();
8、 泛型上下限:
8.1、泛型上限
泛型的上限:
格式: 类型名称 <? extends 类 > 对象名称
意义: 只能接收该类型及其子类
? extends Person: Person类型或者Person类型的子类型,表示继承Person的类;
? extends E: E类型或者E类型的子类型
public static void print(ArrayList<? extends Person> list) {
8.2、泛型下限:
格式: 类型名称 <? super 类 > 对象名称
意义: 只能接收该类型及其父类型
? super Teacher: Teacher类型或者Teacher类型的父类型,表示父类是Teacher的类;
? super E: E类型或者E类型的父类型
public static void print(ArrayList<? super Teacher> list) {
三、List接口
1、List接口特点:
—它是一个元素存取有序的集合。
—它是一个带有索引的集合;
—集合中可以有重复的元素;
常用方法:
- add(int index, E element) : 将指定的元素,添加到该集合中的指定位置上。
- get(int index) :返回集合中指定位置的元素。
- remove(int index) : 移除列表中指定位置的元素, 返回的是被移除的元素。
- set(int index, E element) :替换集合中元素,返回值的更新前的元素;
2、常见数据结构:
数据存储的常用结构有:栈、队列、数组、链表和红黑树。
——栈:
又称堆栈,运算受限的线性表,仅允许在标的一端进行插入和删除操作;
特点:
先进后出:
栈的入口、出口的都是栈的顶端位置。
压栈:就是存元素。
弹栈:就是取元素。
——队列:
运算受限的线性表,仅允许在表的一端进行插入,而在表的另一端进行删除。
先进先出;
队列的入口、出口各占一侧。
——数组:
有序的元素序列
查找元素快;增删元素慢;
在指定索引位置增加元素和删除元素;
——链表:
由一系列结点组成,其中每个结点包括两个部分:
一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域;
链表结构有单向链表与双向链表;
特点:
多个结点之间,通过地址进行连接。
查找元素慢:增删元素快:
——红黑树:
二叉树是每个节点最多有两个子树的树结构。
顶上的叫根结点,两边被称作“左子树”和“右子树”。
3、LinkedList集合:
LIst集合下面ArrayList集合和LinkedList集合;
LinkedList 集合数据存储的结构是链表结构。方便元素添加、删除的集合。
常用方法:
- addFirst(E e) :将指定元素插入此列表的开头。
- addLast(E e) :将指定元素添加到此列表的结尾。
- getFirst() :返回此列表的第一个元素。
- getLast() :返回此列表的最后一个元素。
- removeFirst() :移除并返回此列表的第一个元素。
- removeLast() :移除并返回此列表的最后一个元素。
- pop() :从此列表所表示的堆栈处弹出一个元素。
- push(E e) :将元素推入此列表所表示的堆栈。
- isEmpty() :集合是否为空,为空返回true;
四、set接口:
Set集合取出元素的方式可以采用:迭代器、增强for。
HashSet是Set 接口的一个实现类;
特点:
存储的元素是不可重复的,并且元素都是无序的;
根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存储和查找性能。
哈希表是由数组+链表+红黑树;
保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的;
就必须复写hashCode和equals方法建立属于当前对象的比较方式。
1、LinkedHashSet:
链表和哈希表组合:保证了存入其中元素而的有序性,和唯一性;
Set<String> set = new LinkedHashSet<String>();
五、Collections工具类:
Collections 是集合工具类,用来对集合进行操作:
shuffle(List<?> list)
:打乱集合顺序。
public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序。public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。
int类型按照升序进行排列;
string类型,按照字母的ASC码进行排序的;
//排序方法
Collections.sort(list);
sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序;
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()‐o2.getAge();//以学生的年龄升序
}
五、Map集合
1、概念
映射:身份证号与个人,这种一一对应的关系;
Collection 中的集合称为单列集合, Map 中的集合称为双列集合;
特点:
Map 中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
2、Map集合子类:
HashMap:存储数据采用的哈希表结构,
元素的存取顺序不能保证一致。
保证键唯一、不重复,需要重写键的hashCode()方法、equals()方法。
LinkedHashMap:HashMap下有个子类LinkedHashMap,
存储数据采用的哈希表结构+链表结构。
通过链表结构保证元素的存取顺序一致;
通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
3、常用方法:
- put(K key, V value) : 把指定的键与指定的值添加到Map集合中。
- remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的
- get(Object key) 根据指定的键,在Map集合中获取对应的值。
- Set keySet() : 获取Map集合中所有的键,存储到Set集合中。
- Set> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)。
- containKey(Object key) :判断该集合中是否有此键;
4、Map的遍历:
——键找值方式:
- 获取Map中所有的键(keyset())
- 遍历键的Set集合,得到每一个键。
- 根据键,获取键所对应的值。(get(K key))
// 1、将key以Set形式取出
Set<Object> keySet = hashMap.keySet();
// 2、将key转为迭代器
Iterator<Object> iterator = keySet.iterator();
// 3、遍历取值
while (iterator.hasNext()) {
String key = iterator.next().toString();
String value = hashMap.get(key).toString();
System.out.println(key + "==" + value);
}
——键值对方式
使用方法:
Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)。
那么同样Entry中,获取键和获取值的方法:
getKey() :获取Entry对象中的键。
getValue() :获取Entry对象中的值。
1、获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。— entrySet() 。
2、遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
3、通过键值对(Entry)对象,获取Entry对象中的键与值。——getkey() getValue()
// 1、获取键值对(Entry)对象
Set<Map.Entry<Object, Object>> entries = hashMap.entrySet();
// 2、转为迭代器
Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();
// 3、遍历取值
while (iterator.hasNext()) {
Map.Entry<Object, Object> next = iterator.next();
String key = next.getKey().toString();
String value = next.getValue().toString();
System.out.println(key + "==" + value);
}
5、可变参数:
public static int getSum(int… arr) :可变参数的使用格式;
int sum = getSum(6, 7, 2, 12, 2121);//调用方法;
public static int getSum(int... arr) {//接受数值
int sum = 0;
for (int a : arr) {//遍历求和
sum += a;
}
}
注意:
1.一个方法只能有一个可变参数
2.如果方法中有多个参数,可变参数要放到最后。
Collections中也提供了添加一些元素方法:
//往集合中添加一些元素;
public static <T> boolean addAll(Collection<T> c, T... elements)
具体应用:
ArrayList<Integer> list = new ArrayList<Integer>();
//采用工具类 完成 往集合中添加元素
Collections.addAll(list, 5, 222, 1,2);
6、 HashSet集合存储数据的结构(哈希表)(扩容机制)
在JDK1.8之前,哈希表底层采用数组+链表实现,即使用数组处理冲突,同一hash值的链表都存储在一个数组里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的。
六、xmind整理
图: