目录
浅谈
Array数组
初始化(动与静)
动态初始化
静态初始化
CRUD
增
查
索引取值
遍历
改
删
走进底层
栈与堆
一个数组的诞生
多数组
避坑指南
索引越界
空指针异常
小试牛刀
Collection
List部落
介绍和特点
方法
ArrayList
介绍
方法
遍历
LinkedList
介绍
方法(特有)
Set部落
介绍
方法
HashSet
介绍
唯一性
LinkedHashSet
介绍
TreeSet
介绍
自然排序
比较器排序
Map
介绍和特点
方法的介绍
介绍
示例
遍历方式
浅谈
-
容器: 容器是能够盛放物质的器皿,比如水杯,可以盛放水
- 编程语言中的容器: 用于存储数据的数据结构,称为容器
Java中的容器可以整体认为三类: Array、Collection 和 Map,图中加粗是重点学习对象
Array数组
初始化(动与静)
动态初始化
// 动态初始化:数组动态初始化就是只给定数组长度, 由系统给出默认初始化值
// 动态初始化格式:数组类型[] 数组名 = new 数组类型[数组长度]
// 示例: int[] arr = new int[3] // 数组类型为int类型, 数组名为arr, 数组长度为3
// 示例: 动态初始化一个长度为5的数组, 并循环打印内部的所有元素
public class DemoTh {
public static void main(String[] args) {
// 动态初始化一个长度为5的数组
int[] arr = new int[5];
System.out.println(arr);
}
}
静态初始化
// 静态初始化: 数组静态初始化是指在创建数组时, 直接将元素确定.
// 静态初始化格式:
// 完整版:数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, ....}
// 简化版:数组类型[] 数组名 = {元素1, 元素2, ....}
// 示例:创建一个包含1, 3, 5, 7, 9的数组, 并遍历输出其每一个元素
public class DemoOneToNine {
public static void main(String[] args) {
// 静态初始化数组
int[] arr = {1, 3, 5, 7, 9};
System.out.println(arr);
}
}
CRUD
增
看初始化
查
索引取值
- 索引即下标,代表元素在数组中的位置。Java数组的索引从0开始
public class DemoOneToNine {
public static void main(String[] args) {
// 静态初始化数组
int[] arr = {1, 3, 5, 7, 9};
System.out.println(arr[3]); // 7
}
}
遍历
// for循环示例: 按索引取出元素
public class DemoOneToNine {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0;i<arr.length;i++) {
System.out.println(arr[i]);
};
}
}
// for循环示例: 直接遍历出元素
public class DemoOneToNine {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
for(int item:arr) {
System.out.println(item);
}
}
}
改
public class Test01 {
public static void main(String[] args) {
// 静态初始化数组
int[] arr = {1, 3, 5, 7, 9};
arr[0] = 666;
for(int item:arr) {
System.out.println(item);
}
}
}
删
走进底层
栈与堆
- 栈:保存局部变量的值,包括:基本数据类型的值、类的实例(堆区对象的引用(指针)。
- 堆:用来存放动态产生的数据,比如new出来的对象。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法,并不是每创建一个对象就把成员方法复制一次。
一个数组的诞生
public class JavaMem {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println(arr);
}
}
多数组
arr2 = arr1
public class JavaMem {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;
System.out.println(arr1[0]); // 1
System.out.println(arr2[0]); // 1
arr1[0] = 66;
System.out.println(arr1[0]); // 66
System.out.println(arr2[0]); // 1
}
}
arr2 = {arr1[0], arr1[1], arr1[2]}
public class JavaMem {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3};
int[] arr2 = {arr1[0], arr1[1], arr1[2]};
System.out.println(arr1[0]); // 1
System.out.println(arr2[0]); // 1
arr1[0] = 666;
System.out.println(arr1[0]); // 66
System.out.println(arr2[0]); // 66
}
}
避坑指南
索引越界
索引越界是指使用索引获取数组元素时, 使用的索引不能超过数组元素的最大索引值, 超过后无法通过改索引获取指定的元素, 就会出现索引越界错误, 异常名称位: ArrayIndexOutOfBoundsException
空指针异常
当一个数组对象被创建了, 当使用的过程中如果让数组对象指向了null, 即将null赋值给数组, 意味着变量arr将不会再保存数组的内存地址,也就不允许再操作数组了,因此运行的时候会抛出 NullPointerException 空指针异常。
小试牛刀
找出数组的最大值
public class GetMax {
public static void main(String[] args) {
int[] my_arr = {1, 5, 2, 0, -9, 8, 4};
int max = my_arr[0];
for (int i = 1; i < my_arr.length; i++) {
if (my_arr[i] > max) {
max = my_arr[i];
}
}
System.out.println(max);
}
}
返回两个元素的和等于定值,的这两个元素的索引
public class FindTarget {
public static void main(String[] args) {
int target = 8;
int[] arr = {1, 3, 5, 7, 9};
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] + arr[j] == target) {
System.out.println("索引分别为: " + i + "," + j);
}
}
}
}
}
Collection
List部落
介绍和特点
- List集合为有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素, 并搜索列表中的元素
- 列表通常允许重复的元素
- 特点:(1) 有索引 (2) 可以存储重复元素 (3) 元素存取有序
方法
方法名 | 描述 |
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
ArrayList
介绍
在java中ArrayList提供一种存储空间可变的存储模型, 存储的数据容量是可以发生改变的. ArrayList底层是「数组」实现的, 长度可以变化.
方法
方法名 | 说明 |
public boolean add(E e) | 将指定的元素追加到此集合的末尾 |
public void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 |
public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
public E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合中的元素的个数 |
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
//创建ArrayList集合对象, 添加四个元素, 并输出在控制台中
ArrayList<String> al = new ArrayList<>();
al.add("Hello");
al.add("World");
al.add("Hello");
al.add("Java");
System.out.println("al的值:" + al);
//获取索引为1的元素, 输出在控制台中
System.out.println("al索引为1的元素: " + al.get(1));
//修改索引为3的元素为"Hi"
al.set(3,"Hi");
//查看修改后的al
System.out.println("修改索引为3的元素后的al: " + al);
//移除索引为0的元素后输出al
al.remove(0);
System.out.println("移除索引为0的元素后的al: " + al);
//移除内容为"Java"的元素后输出al
al.remove("Java");
System.out.println("移除Java后的al: " + al);
}
}
遍历
import java.util.ArrayList;
public class ArrayListIterDemo {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("I");
al.add("love");
al.add("you");
//普通for遍历
for (int i=0;i<al.size();i++){
System.out.println(al.get(i));
};
// 增强for遍历
for (String item : al) {
System.out.println(item);
}
}
}
LinkedList
介绍
LinkedList功能与ArrayList一样,同样是一个List的实现类,功能也是存储数据使用。但LinkedList与ArrayList本质完全不同。
- ArrayList:底层有数组实现
- LinkedList:底层有链表实现
方法(特有)
方法名 | 说明 |
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的第一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<Integer> numbers_linklist = new LinkedList<>();
numbers_linklist.add(1);
numbers_linklist.add(2);
numbers_linklist.add(3);
numbers_linklist.add(4);
numbers_linklist.add(5);
// addFirst方法
numbers_linklist.addFirst(0);
System.out.println(numbers_linklist);
// addLast方法
numbers_linklist.addLast(6);
System.out.println(numbers_linklist);
// getFirst方法
System.out.println(numbers_linklist.getFirst());
// getLast方法
System.out.println(numbers_linklist.getLast());
// removeFirst方法
numbers_linklist.removeFirst();
System.out.println(numbers_linklist);
// removeLast方法
numbers_linklist.removeLast();
System.out.println(numbers_linklist);
}
}
Set部落
介绍
Set为集合,不包含重复元素的集合, 并且最多只有一个空元素。
方法
方法名 | 说明 |
add(E e) | 如果指定的元素不存在,则将其指定的元素添加(可选操作)。 |
clear() | 从此集合中删除所有元素(可选操作)。 |
contains(Objcet o) | 如果此集合包含指定的元素,则返回 true 。 |
equals(Object o) | 将指定的对象与此集合进行比较以实现相等。 |
hashCode() | 返回此集合的哈希码值。 |
isEmpty() | 如果此集合不包含元素,则返回 true 。 |
remove(Object o) | 如果存在,则从该集合中删除指定的元素(可选操作)。 |
size() | 返回此集合中的元素数(其基数)。 |
toArray() | 返回一个包含此集合中所有元素的数组。 |
HashSet
介绍
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历(可以使用增强for循环和迭代器实现遍历)
- 由于是Set集合,所以是不包含重复元素的集合
唯一性
前置知识:HashTable: 哈希表;HashCode: 哈希值
- a.根据对象的哈希值计算存储位置(哈希值对16取模即可得到存储位置, 一个HashSet默认存储16个元素)
- 如果当前位置没有元素则直接存入
- 如果当前位置有元素存在,则进入第二步
- b.当前元素和已经存在的元素比较哈希值
- 如果哈希值不同,则将当前元素进行存储
- 如果哈希值相同,则进入第三
- c.通过equals()方法比较两个元素的内容
- 如果内容不相同,则将当前元素进行存储
- 如果内容相同,则不存储当前元素
LinkedHashSet
介绍
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
TreeSet
介绍
- TreeSet元素排序方式取决于构造方法
- Comparable(自然排序): 创建TreeSet对象时, 使用TreeSet()无参构造
- Comparator(比较器): 创建TreeSet对象时, 使用TreeSet(Comparator comparator)有参构造方法, 传递的参数是Comparator接口的实现类对象, 则根据指定的比较器进行排序
- TreeSet没有带索引的方法, 所以不能使用普通for循环遍历
- 由于是Set集合, 所以不能存储重复的元素
public class TreeSetDemo01 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Integer> ts = new TreeSet<Integer>();
//添加元素
ts.add(10);
ts.add(40);
ts.add(30);
ts.add(50);
ts.add(20);
ts.add(30);
//遍历集合
for(Integer i : ts) {
System.out.println(i);
}
}
}
自然排序
自然排序是在添加对象到集合内部时, 让其按照对象内部的比较方法进行自动排序. 构建TreeSet时使用无参构造方法即可.
上面的例子中, 我们构建ts对象, 并向其中添加一些整型, 遍历ts对象会发现, 打印的顺序是从小到达的. 经查看Integer类源码发现, Integer底层实现了两个方法, 一个compare方法和compareTo方法, 其中compare负责进行比较, 而compareTo内部调用compare方法, 当前数与另一个数进行比较时, 如果当前数小于那个数, 则返回-1, 如果相等则返回0, 如果当前数大于那个数则返回1. 如果是自定义类实例化而来的对象, 需要自己定义compareTo()方法, 在方法内部定义比较规则.
需求:定义学生类, 学生类内部定义compareTo方法, 按照学生年龄排序. 将学生类添加至TreeSet对象中, 遍历集合对象
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student(){};
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Student s) {
return this.age - s.age;
}
}
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();
Student s1 = new Student("成成", 18);
Student s2 = new Student("宝中", 17);
Student s3 = new Student("金喜", 20);
ts.add(s1);
ts.add(s2);
ts.add(s3);
for (Student stu : ts) {
System.out.println(stu.getName());
}
}
}
比较器排序
使用比较器排序, 需要自己实现一个比较器, 并在初始化TreeSet时使用有参构造, 并把比较器传入进去, 对象加入TreeSet对象时, 就会按照比较器的规则进行排序了
需求:定义学生类, 学生类内部定义compareTo方法, 按照学生年龄排序. 将学生类添加至TreeSet对象中, 遍历集合对象
public class Student {
private String name;
private int age;
public Student(){};
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>(
new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return s1.getAge() - s2.getAge();
}
}
);
Student s1 = new Student("小明", 18);
Student s2 = new Student("小红", 17);
Student s3 = new Student("小强", 20);
ts.add(s1);
ts.add(s2);
ts.add(s3);
for (Student stu : ts) {
System.out.println(stu.getName());
};
}
}
Map
介绍和特点
Map为一个接口, 将键映射到值的对象。 Map不能包含重复的键; 每个键可以映射到最多一个值。
interface Map<K,V> K:键的类型;V:值的类型
特点:
- 键值对映射关系
- 一个键对应一个值
- 键不能重复, 值可以重复
- 元素存取无序
基本使用:
import java.util.HashMap;
import java.util.Map;
public class MapDemo01 {
public static void main(String[] args) {
//创建HashMap对象
Map<String, String> m = new HashMap<String, String>();
//添加键值对
m.put("name_1", "Jeremy");
m.put("name_2", "Fish");
//输出
System.out.println(m); //{name_2=Fish, name_1=Jeremy}
}
}
方法的介绍
介绍
//增:
- put(key, value): 添加键值对, 返回键对应的值
//删:
- remove(key, value): 如果指定的键对应的值为value, 则进行删除
- remove(key): 根据键删除键值对元素, 返回键对应的值
- clear(): 清空所有键值对元素
//改:
- put(key, value): 同则修改, 异则添加
//查:
- containsKey(key): 判断是否存在某个特定的key, 返回值为布尔值
- containsValue(Value): 判断是否包含指定的值, 返回值为布尔值
- isEmpty(): 判断Map对象是否为空, 返回值为布尔值
- size(): 获取Map对象键值对个数, 返回值为整型
- get(key): 获取指定键的值
- keySet(): 获取所有的键, 返回值为Set类型
- Values(): 获取所有值的集合
- enterSet(): 获取所有键值对对象的集合
示例
import java.util.HashMap;
import java.util.Map;
public class MapDemo01 {
public static void main(String[] args) {
Map<String, String> m = new HashMap<String, String>();
m.put("name_1", "Jeremy");
m.put("name_2", "Fish");
System.out.print("put增加键值对后的m为: ");
System.out.println(m); //put增加键值对后的m为: {name_2=Fish, name_1=Jeremy}
m.remove("name_1", "Jer");
System.out.print("如果键name_1对应的值为Jer, 则移除: ");
System.out.println(m); //如果键name_1对应的值为Jer, 则移除: {name_2=Fish, name_1=Jeremy}
//直接移除name_1的键值对
m.remove("name_1");
System.out.print("移除name_1的键值对后, m的值: ");
System.out.println(m); //移除name_1的键值对后, m的值: {name_2=Fish}
//clear()后的m
m.clear();
System.out.print("clear()后m的值为: ");
System.out.println(m); //clear()后m的值为: {}
//空对象m重新添加name_1键值对
m.put("name_1", "Jeremy");
m.put("name_2", "Lucy");
System.out.print("重新添加name_1键值对的m为: ");
System.out.println(m); //重新添加name_1键值对的m为: {name_2=Lucy, name_1=Jeremy}
//重复添加name_1的键, 但是改变对应的值
m.put("name_1", "LiLi");
System.out.print("使用name_1键的新值覆盖原有值后m的值: ");
System.out.println(m); //使用name_1键的新值覆盖原有值后m的值: {name_2=Lucy, name_1=LiLi}
//判断是否包含指定的key
System.out.println(m.containsKey("name_2")); //true
//判断是否包含指定的value
System.out.println(m.containsValue("Lucy")); //true
//判断是否为空
System.out.println(m.isEmpty()); //false
//获取Map对象的长度
System.out.println(m.size()); //2
//获取指定键对应的值
System.out.println(m.get("name_1")); // LiLi
//获取所有键的集合
System.out.println(m.keySet()); //[name_2, name_1]
//获取所有值的集合
System.out.println(m.values()); //[Lucy, LiLi]
//获取所有的键值对
System.out.println(m.entrySet()); //[name_2=Lucy, name_1=LiLi]
}
}
遍历方式
方式一
使用增强for, 遍历集合的所有键或值进行操作
import java.util.HashMap;
import java.util.Map;
public class MapDemo02 {
public static void main(String[] args) {
Map<String, String> m = new HashMap<String, String>();
m.put("name_1", "金喜");
m.put("name_2", "帅帅");
m.put("name_3", "晨阳");
for(String key: m.keySet()){
System.out.println(key);
}
for (String value:m.values()){
System.out.println(value);
}
}
}
方式二
通过增强for遍历键值对组成的EntrySet对象
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo03 {
public static void main(String[] args) {
Map<String, String> m = new HashMap<String, String>();
m.put("name_1", "Jeremy");
m.put("name_2", "刘桂宁");
m.put("name_3", "毕奎成");
Set<Map.Entry<String, String>> items = m.entrySet();
for(Map.Entry<String, String> item:items) {
System.out.println("键值对为: " + item);
System.out.println("键为: " + item.getKey());
System.out.println("值为: " + item.getValue());
System.out.println("-------------------------");
}
}
}