Java 集合
对象的容器,定义了对多个对象进行操作的常用方法。
位于java.util.*包下
数组
- 长度固定
- 既可以存储基本数据类型,又可以存储引用数据类型
集合
- 长度不固定
- 只能存储引用数据类型
Collection 集合
Collection 父接口,代表一组任意类型的对象,无序,无下标。
| 方法 | 方法描述 |
|---|---|
| boolean add(Object obj) | 添加⼀个对象数据 |
| boolean addAll(Collection c) | 将⼀个集合中的所有对象添加到此集合中 |
| void clear() | 清空此集合中的所有对象 |
| boolean contains(Object o) | 检查此集合中是否包含o对象 |
| boolean equals(Object o) | ⽐较此集合是否与指定对象相等 |
| boolean isEmpty() | 判断此集合是否为空 |
| boolean remove(Object o) | 在此集合中移除o对象 |
| int size() | 返回此集合中的元素个数 |
| Object[] toArray() | 将此集合转换成数组 |
注:遍历同时不能使用集合删除方法,否则出现并发修改异常,可使用迭代器的删除方法。
List
特点:有序、有下标、元素可以重复 继承
Collection接口
| 方法 | 方法描述 |
|---|---|
| void add(int index, Object o) | 在index位置插⼊对象o |
| boolean addAll(int index, Collection c) | 将⼀个集合中的元素添加到此集合中的index位置 |
| Object get(int index) | 返回集合中指定位置的元素 |
| List subList(int fromIndex, int toIndex) | 返回fromIndex和toIndex之间的集合元素 |
public class TestList {
public static void main(String[] args) {
List list = new ArrayList();
list.add("Apple");
list.add("Pear");
list.add("Banana");
// 遍历的方法
// 1. for 循环
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 2. 增强 for 循环
for (Object object : list) {
String string = (Object) object;
System.out.println(string);
}
// 3. 迭代器
Iterator it = list.listIterator();
while(it.hasNext()) {
System.out.println(it.next());
}
// 4. 列表迭代器,和Iterator的区别,ListIterator可以向前或向后遍历,添加、删除、修改元素
ListIterator lit = list.listIterator();
while(lit.hasNext()) {
System.out.println(lit.nextIndex() + "..." + lit.next());
}
while(lit.hasPrevious()) {
System.our.println(lit.previousIndex() + "..." + lit.previous());
}
}
}
ArrayList
数组结构实现、查询快、增删慢。存储结构是数据。 JDK1.2 线程不安全
add方法源码分析
remove方法源代码分析
LinkedList
链表结构实现、查询慢、增删快。存储结构是双向链表。 JDK1.2 线程不安全
Vector
数组结构实现,查询快,增删慢。 JDK1.0 线程安全、运行效率比 ArrayList 较慢
数据结构
- 栈:先进后出
- Stack类:继承
Vector类 push方法入栈、pop方法出栈LinkedList也实现了栈结构
- Stack类:继承
- 队列:先进先出
- Queue接口:继承
Collection接口 offer方法入队、poll方法出队LinkedList实现了Queue接口
- Queue接口:继承
泛型
Java 泛型是JDK1.5中引入的一个新特性,其本质就是参数化类型,把类型作为参数传递。 泛型分类:泛型类、泛型接口、泛型方法。
T称为类型占位符,表示一种引用数据类型。
- 泛型类
public class Generic<T> {
T t;
public void show(T t) {
System.out.println(t);
}
}
- 泛型接口
// 接口
public interface USB<T> {
T service(T t);
}
// 实现
public class Mouse<T> implements USB<T>{
@Override
public T service(T t) {
return t;
}
}
- 泛型方法
public class Generic {
public <T> T show(T t) {
return t;
}
}
注意事项
- 泛型不能在类中声明静态属性、静态常量
static修饰的属性是静态属性,先于对象,泛型类型取决于创建对象时传入的实际类型
- 泛型不能在类中初始化对象或数组,但是可以声明对象或数组
- 实例化对象需要分配空间,没有确定类型不能开辟空间
- 初始化数组时需要给元素进行分配空间,泛型类型不确定,无法分配空间
- 在类中不能使用泛型声明参数个数相同的重载方法
- 使用不同实际类型创建出的泛型类对象的引用不可以相互赋值
泛型集合
参数化类型、类型安全的集合,强制集合的元素类型必须一致
- 特点
- 编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换(拆箱)
- 不同泛型之间引用不能相互赋值
Set
特点:无序、无下标,元素不可重复 方法全部继承至
Collection中的方法
HashSet
基于
equals,hashCode实现元素不重复 当存入元素的哈希码相同时,会调用==或equals进行确认,结果为true,拒绝后者进入
public class TestHashSet {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(30);
set.add(20);
set.add(10);
set.add(60);
set.add(10);
set.add(20);
//
System.out.println(set.size());
System.out.println(set);
// 增强 fro
for (Integer i : set) {
System.out.print(i + " ");
}
// 迭代器
Iterator it = set.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
System.out.println();
System.out.println(set.contains(20));
set.remove(10);
System.out.println(set);
set.clear();
System.out.println(set);
System.out.println(set.isEmpty());
}
}
LinkedSet
链表实现的
HashSet,按照链表进行储存,即可保留元素的插入顺序
public class TestLinkedHashSet {
public static void main(String[] args) {
LinkedHashSet<Integer> set = new LinkedHashSet<>();
set.add(1);
set.add(2);
set.add(3);
System.out.println(set);
}
}
TreeSet
- 基于排列顺序实现元素不重复
- 实现了
SortedSet接口,对集合元素自动排序 - 元素对象的类型必须实现
Comparable接口,指定排序规则 - 通过
CompareTo方法确定是否为重复元素
public class TestTreeSet {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<>();
set.add(20);
set.add(10);
set.add(30);
set.add(50);
System.out.println(set);
set.add(15);
System.out.println(set);
System.out.println(set.contains(30));
set.remove(20);
System.out.println(set);
set.clear();
System.out.println(set.isEmpty());
}
}
Comparator 比较器
可以实现定制比较,元素自身提供的比较规则称为自然排序。
使用
Comparator比较器,元素类型可不实现Comparable接口,并且优先级高于Comparable接口。
public class TestComparator {
public static void main(String[] args) {
Student s1, s2, s3, s4;
s1 = new Student(3213, "John", "男", 100);
s2 = new Student(3212, "Jack", "男", 99);
s3 = new Student(3211, "Rose", "女", 99);
s4 = new Student(3213, "John", "男", 100);
// 使用了Comparator比较器,匿名内部类实现compara方法,使用学生学号进行比较
Set<Student> students = new TreeSet<>(((o1, o2) -> Integer.compare(o1.getSID(), o2.getSID())));
students.add(s1);
students.add(s2);
students.add(s3);
students.add(s4);
System.out.println(students);
}
}
// 定义一个Student类
public class Student {
private int SID;
private String name;
private String sex;
private double score;
public Student() {
}
public Student(int SID, String name, String sex, double score) {
this.SID = SID;
this.name = name;
this.sex = sex;
this.score = score;
}
public int getSID() {
return SID;
}
public void setSID(int SID) {
this.SID = SID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"SID=" + SID +
", name='" + name + ''' +
", sex='" + sex + ''' +
", score=" + score +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student student)) return false;
return SID == student.SID && Double.compare(score, student.score) == 0 && Objects.equals(name, student.name) && Objects.equals(sex, student.sex);
}
@Override
public int hashCode() {
return Objects.hash(SID, name, sex, score);
}
}
Map 集合
特点:称为“映射”存储一对数据(Key-Value),键不可以重复,值可以重复。
| 方法 | 描述 |
|---|---|
| V put(K key, V value) | 将对象存入到集合中,关联键值。key重复则覆盖原值 |
| Set<K> keySet() | 返回所有key |
| Collection<V> values | 返回包含所有值的Collection集合 |
| Set<Map.Entry<K,V>> entrySet() | 键值匹配的Set集合 |
HashMap
JDK1.2版本,线程不安全,运行效率快;允许
null作为key或value。
public class TestHashMap {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("cn", "中国");
map.put("uk", "英国");
map.put("us", "美国");
map.put("cn", "中华人民共和国");
System.out.println(map.size());
System.out.println(map);
System.out.println(map.get("cn"));
// 遍历
// 1. 键集合遍历
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.print(map.get(key) + " ");
}
System.out.println();
// 2. 迭代器
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
System.out.print(map.get(iterator.next()) + " ");
}
System.out.println();
System.out.println("-----------------------------------------");
// entrySet
// 1. 增强 for
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for (Map.Entry<String, String> reflection : entrySet) {
System.out.println(reflection.getKey() + "..." + reflection.getValue());
}
System.out.println("-----------------------------------------");
// 2. 迭代器
Iterator<Map.Entry<String, String>> entryIterator = map.entrySet().iterator();
while (entryIterator.hasNext()) {
Map.Entry<String, String> reflection = entryIterator.next();
System.out.println(reflection.getKey() + "..." + reflection.getValue());
}
}
}
LinkedHashMap
有顺序的
HashMap
public class TestLinkedHashMap {
public static void main(String[] args) {
LinkedHashMap<Integer, String> hashMap = new LinkedHashMap<>();
hashMap.put(2, "two");
hashMap.put(1, "one");
hashMap.put(3, "three");
System.out.println(hashMap);
}
}
// 结果为
{2=two, 1=one, 3=three} // 有顺序
TreeMap
实现了
SortMap接口,可以对key进行自动排序,key需要实现Comparable接口
public class TestTreeMap {
public static void main(String[] args) {
Student s1, s2, s3, s4;
s1 = new Student(3310, "John", "男", 100);
s2 = new Student(3311, "Jack", "男", 99);
s3 = new Student(3312, "Rose", "女", 99.5);
s4 = new Student(3310, "John", "男", 100);
// 创建TreeMap对象,并传入排序依据,使用匿名内部类 -> 实现Comparator接口
TreeMap<Student, String> treeMap = new TreeMap<>(((o1, o2) -> Double.compare(o1.getScore(), o2.getScore())));
treeMap.put(s1, "东京");
treeMap.put(s2, "南京");
treeMap.put(s3, "天津");
treeMap.put(s4, "北京");
System.out.println(treeMap);
Set<Student> studentSet = treeMap.keySet();
for (Student student : studentSet) {
System.out.println(student.getName() + "..." + treeMap.get(student));
}
Set<Map.Entry<Student, String>> entries = treeMap.entrySet();
for (Map.Entry<Student, String> entry : entries) {
System.out.println(entry.getKey().getName() + "..." + entry.getKey().getScore() + "..." + entry.getValue());
}
treeMap.remove(new Student(3310, "John", "男", 100));
System.out.println(treeMap);
System.out.println(treeMap.containsValue("东京"));
System.out.println(treeMap.containsKey(s2));
System.out.println(treeMap.isEmpty());
treeMap.clear();
System.out.println(treeMap.isEmpty());
System.out.println(treeMap);
}
}
HashTable
JDK1.0版本,线程安全,运行效率慢;不允许
null作为key或value。
Properties
HashTable 的子类,要求
key或value都是String。通常用于配置文件的读取。
public class TestProperties {
public static void main(String[] args) {
Properties properties = new Properties();
properties.put("name", "jack");
properties.put("country", "China");
properties.put("hobby", "eating");
System.out.println(properties);
// 使用stringPropertyNames()方法获取所有属性名集合
Set<String> propertyNames = properties.stringPropertyNames();
for (String propertyName : propertyNames) {
System.out.println(propertyName + "..." + properties.getProperty(propertyName));
}
System.out.println(properties.containsKey("name"));
System.out.println(properties.containsValue("china"));
// System.getProperties()获取所有系统属性
Properties properties1 = System.getProperties();
Set<String> propertyNames1 = properties1.stringPropertyNames();
for (String string : propertyNames1) {
System.out.println(string + "..." + properties1.getProperty(string));
}
}
}
HashMap源码分析