参考:https://how2j.cn/k/collection/collection-arraylist/363.html?p=136471
1.容器的优势
数组的局限性:比如 声明长度是10的数组不用的数组就浪费了,超过10的个数,又放不下
为了解决数组的局限性,引入容器类的概念。 最常见的容器类就是 ArrayList
容器的容量"capacity"会随着对象的增加自动增长 ,只需要不断往容器里增加英雄即可,不用担心会出现数组的边界问题。
2.ArrayList
维护索引和对应索引的值
常用方法:add,get,indexOf,set,remove,size,contains,addAll,clear
ArrayList heros = new ArrayList();
heros.add(new Hero("hero")); // 追加
heros.add(3, specialHero); // 插入指定位置
heros.contains(specialHero) // 判断容器中是否存在
heros.get(5) // 索引取值
heros.indexOf(specialHero)
heros.remove(2); // 根据索引删除
heros.remove(specialHero); //根据对象删除
heros.set(5, new Hero("hero 5")); //替换对应索引的值
heros.size()
Hero hs[] = (Hero[])heros.toArray(new Hero[]{}); //转换为数组,需要提供类型,默认转Object数组
heros.addAll(anotherHeros); // 容器扩展
heros.clear(); //清空
// ArrayList实现了接口List,常见的写法会把引用声明为接口List类型 java.util.List
List heros = new ArrayList();
3.泛型
不指定泛型的容器,可以存放任何类型的元素,指定了泛型的容器,只能存放指定类型的元素以及其子类
ArrayList 默认接受Object类型的对象,若不指定泛型 取出对象为Objecs类型,需要强制转换后才能调用对应类型的方法(如强制转换为APHero类型或者ADHero类型)
//声明容器的时候,就指定了这种容器,只能放Hero,放其他的就会出错
List<Hero> genericheros = new ArrayList<Hero>();
// List<Hero> genericheros2 = new ArrayList<>(); 简写
genericheros.add(new Hero("盖伦"));
//如果不是Hero类型,根本就放不进去
//genericheros.add(new Item("冰杖")); 报错
//除此之外,还能存放Hero的子类
genericheros.add(new APHero());
//并且在取出数据的时候,不需要再进行转型了,因为里面肯定是放的Hero或者其子类
Hero h = genericheros.get(0);
4.ArrayList遍历
List<Hero> heros = new ArrayList<Hero>();
// 放5个Hero进入容器
for (int i = 0; i < 5; i++) {
heros.add(new Hero("hero name " + i));
}
// 第一种遍历 for循环
for (int i = 0; i < heros.size(); i++) {
Hero h = heros.get(i);
System.out.println(h);
}
//第二种遍历,使用迭代器
Iterator<Hero> it= heros.iterator();
//从最开始的位置(空位置,索引0的前一个)判断"下一个"位置是否有数据
//如果有就通过next取出来,并且把指针向下移动,直到"下一个"位置没有数据
while(it.hasNext()){
Hero h = it.next();
System.out.println(h);
}
//迭代器的for写法
for (Iterator<Hero> iterator = heros.iterator(); iterator.hasNext();) {
Hero hero = (Hero) iterator.next();
System.out.println(hero);
}
// 第三种,增强for循环,无法进行ArrayList的初始化,无法获得索引,但可以自定义下表变量
for (Hero h : heros) {
System.out.println(h);
}
5.LinkedList
与ArrayList一样,LinkedList也实现了List接口,因此包含add,remove,contains等等方法
除了实现了List接口外,LinkedList还实现了双向链表结构Deque,可以很方便的操作头尾元素
//LinkedList是一个双向链表结构的list
List<Hero> ll =new LinkedList<Hero>();
//所以可以很方便的在头部和尾部插入数据
ll.addLast(new Hero("hero1"));
//在最前面插入新的英雄
ll.addFirst(new Hero("heroX"));
//查看最前面的英雄
System.out.println(ll.getFirst());
//查看最后面的英雄
System.out.println(ll.getLast());
//取出最前面的英雄
System.out.println(ll.removeFirst());
//取出最后面的英雄
System.out.println(ll.removeLast());
//取出会从容器中删除
System.out.println(ll);
LinkedList 除了实现了List和Deque外,还实现了Queue接口(队列)。
Queue是先进先出队列 FIFO,常用方法:offer 在最后添加元素,poll 取出第一个元素,peek 查看第一个元素
//Queue代表FIFO 先进先出的队列
Queue<Hero> q= new LinkedList<Hero>();
//在最后添加元素
q.offer(new Hero("Hero1"));
//取出第一个Hero,FIFO 先进先出
Hero h = q.poll();
//查看第一个元素
h=q.peek();
6.ArrayList和LinkedList的区别
ArrayList 插入,删除数据慢(需要维护索引);LinkedList插入,删除数据快
ArrayList是顺序结构,所以定位很快,根据索引就能直接找到;
LinkedList 是链表结构,不维护索引,想要找到100号元素,只能遍历过去
从头部添加数据,链表快很多,尾部添加 两个差不多,理论上链表更快(不需要新增最后一个元素的索引)
如果从中间或指定索引插入或修改数据就要看情况了(看是遍历耗时更多还是修改耗时更多)
7.工具类Collections
Collections是容器的工具类,就如同Arrays是数组的工具类
//初始化集合numbers
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
numbers.add(i);
}
Collections.reverse(numbers); //reverse 使List中的数据发生翻转
Collections.shuffle(numbers); // 打乱
Collections.sort(numbers); //排序
Collections.swap(numbers,0,5); // 交换位置
Collections.rotate(numbers,2); // 数据向右滚动
8.HashMap
对应python中的字典
HashMap<String,String> dictionary = new HashMap<>();
dictionary.put("adc", "物理英雄");
System.out.println(dictionary.get("adc"));
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
for (String v : map.values()) {
System.out.println("value= " + v);
}
9.各个容器的区别
ArrayList: 有顺序 ;HashSet(对应python中的集合,没有value的字典): 无顺序
List中的数据可以重复;Set中的数据不能重复(key不能重复),判断的标准:先比较hashcode,不同再比较equals
HashMap中可以使用 null;Hashtable不行