集合的概述
集合(容器)
程序存储数据的方式:
- 变量:单一的数据
- 数组:一组具有相同数据类型的数据
- 1号问题:元素的数据类型都是相同的
- 2号问题:长度不可变
对象:一组具有关联性的数据(变相解决了数组的1号问题)
存储学生(Student)数据:创建学生对象、存储学生姓名、年龄、身高、体重
存储多个学生数据:Student[]
集合:
丰富多样的强大的数据存储(Java给你提供的一大堆API)
集合的体系结构
在Java.util包(工具)。
接口Collection:存储的是可重复(不唯一)、无序的数据
- 接口 List:存储的是可重复(不唯一),有序的数据
使用接口要找他们的实现类
- ArrayList
- LinkedList
- ...
- 接口 Set:存储的是不可重复(唯一),无序的数据
- HashSet
- TreeSet(自动排序)
- ...
接口 Map:存储的是键值对(key键-value值,键和值--对应)数据
- HashMap
- HashTable
- Properties
- TreeMap
- ...
List集合
- list.subList():List<> 截取集合中的一部分,返回出一个子集合
ArrayList
动态数组。
构造方法:
- ArrayList<E>()
常用方法:
-
add(E e) : boolean 存储指定类型(E:泛型类型)的元素
-
add(int index, E element) : void 在指定下标位置存储指定类型的元素,原有位置的元素会依次后移
-
remove(int index) : E 删除指定下标位置的元素,返回被删除的元素
-
remove(Object obj) : boolean 删除指定的元素(如果有重复的,只会删除第一个找到的元素)
-
set(int index, E element) : E 修改指定下标位置的元素,返回被替换的元素
-
get(int index) : E 根据下标查询元素
-
size() : int 查询集合中存储的元素数量
-
contains(Object o) : boolean 判断集合中是否存在指定的元素
-
indexOf(Object o) : int 查询指定元素在集合中的下标,找不到会返回 -1
-
lastIndexOf(Object o) : int 从后往前查找指定元素在集合中的下标,找不到会返回-1
注意:从后往前查找,只不过是方向变化,下标还是正向的下标(不会变!)
-
clear() : void 清空集合
-
isEmpty() : boolean 判断集合是否是空的(没有一个元素)
LinkedList
构造方法:
-
LinkedList<E>()
常用方法(ArrayList的常用方法都可用):
-
addFirst(E e) : void 向前追加元素
-
addLast(E e) : void 向后追加元素
-
removeFirst() : E 删除第一个元素
-
removeLast() : E 删除最后一个元素
-
getFirst() : E 查询第一个元素
-
getLast() : E 查询最后一个元素
-
...
其他方法略,大多和 ArrayList 一致,因为这些方法都是定义在 List 接口中,所以同为 List 接口实现类,当然都会重写相应的方法。
注意:方法名虽然相同,代表的只是方法功能一致,但不代表实现一样!
例如:add()、remove() ...
ArrayList和LinkedList的区别(面试题)
相同点:
- 都是List接口的实现类,可以存储可重复的,有序的数据
不同点:
- ArrayList 底层数据结构是数组结构,在实现数据的查询时,因为数组结构有下标,所以效率较高。但是,在增加或删除数据时,因为数组结构长度不可变,所以会创建一个新的数组,导致效率较低。
它适合于查询较多,增删较少的情况。
- LinkedList 底层数据结构是链表结构,在增加或删除数据时,尤其是首尾的增删,因为链表结构增加节点或删除节点,只需要修改下一个连接的地址即可,效率较高。但是,在实现数据的查询时,没有下标,只能从首节点依次进行查询,效率较低。
它适合于增删较多,查询较少的情况。
Set集合
HashSet
构造方法:
-
HashSet<E>()
常用方法:
-
add(E e) : boolean 存储元素(去重数据)
-
remove(E e) : E 删除数据
-
size() : int 获取集合的元素数量
-
contains(Object o) : boolean 判断是否包含指定的元素
-
clear() : void 清空集合
-
isEmpty() : boolean 判断集合是否是空的(没有一个元素)
-
...
集合的遍历
List集合遍历
1.循环下标实现
例如:遍历新闻数据
for (int i = 0; i < list.size(); i++) {
News news = list.get(i);
System.out.println(news);
}
2.增强 for 实现
例如:遍历新闻数据
for (News news : list) {
System.out.println(news);
}
3.迭代器
// 迭代器:Iterator
// iterator() : Iterator<E>
Iterator<News> iterator = list.iterator();
// hasNext() : boolean 判断是否还有下一个元素
// next() : E 取出下一个元素
// if (iterator.hasNext()) {
// News next = iterator.next();
// System.out.println(next);
// }
while (iterator.hasNext()) {
News next = iterator.next();
System.out.println(next);
}
Set集合遍历
1.增强 for 实现
for (News news : newsSet) {
System.out.println(news);
}
2.迭代器
Iterator<News> iterator = newsSet.iterator();
while (iterator.hasNext()) {
News next = iterator.next();
System.out.println(next);
}
泛型
- 类上
// 集合
public class ArrayList<E> {
}
// 在创建集合对象时,只要指定了 E 的具体类型,那么 add 方法的参数或返回值也就指定了对应的类型
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public E remove(int index) {
}
- 方法上
// Arrays类的方法
// 在调用该方法时,传入什么类型数据,返回的就是什么类型的数据
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
在方法参数中出现了 ... ,它被称为可受参数,比较灵活。
它意味着,你传递多少个指定类型的参数都可以,0个,1个,2个 ...
可以把它在处理时看作是一个数组来处理。
public class Demo03 { public static void main(String[] args) { // printNames(); printNames("张三", "李四", "王五"); } public static void printNames(String... names) { for (String name : names) { System.out.println(name); } } }
- 泛型还可以限制类型必须是某个类型的子类
<? extends 类型>
泛型使用任何符号代表都可以。这些符号就是一个某种类型的表示。
常见的符号:
E(Element,元素)
T(Type,类型)
K(Key,键)
V(Value,值)
....
泛型在指定具体类型时,必须是引用数据类型。
- String
Java给基本类型都准备了相应的引用类型(基本类型相应的包装类型)
-
byte -> Byte
-
short -> Short
-
int -> Integer
-
long -> Long
-
float -> Float
-
double -> Double
-
char -> Character
-
boolean -> Boolean
关于包装类型,后续在分解。