本文目录
导读:祖传挖坟派学习方法(宝儿姐友情支持)
第一部分 List简介
第二部分 何为ArrayList
第三部分 代码示例
第四部分 吹牛
如果你急需想搞清楚一些问题可以先看这里的总结 再后续看文章
(1)ArrayList是线程不安全的
(2)对ArrayList里面对象的使用方法 在第三部分代码示例中 越有可能在开发中用到的方法 比如List转换MAP 都比较靠后
第一部分 List简介
如果你有参阅过 JDK 1.8 API中对于LIST的描述那么 你一定在文中有看到过这句话 This interface is a member of the Java Collections Framework.(此接口是Java集合框架的成员。)
这句话为我们带来了两个提示 首先List是一个接口 其次list是collection接口的子接口,collection是集合的父类型接口 ,定义了所有集合的通用方法 。 翻阅api 我找到了关于list继承关系的结构介绍
观察继承关系 得出如下结论:
一 : E是泛型 意味着 list<E>该方法在调用时可以接收不同类型的参数。可以根据传递给泛型方法的参数类型 .
二: List的父类有两个 第一个是collection 第二个是Iterable collection通过上面铺垫我们有所了解 。 Iterable(迭代器)我这里简短的描述下(是提供一种方法对一个容器对象中的各个元素进行访问,而又不暴露该对象容器的内部细节。)
三:(所有已知的实现类)这里我们看到了 许多但是今天要讲的重点在ArrayList这个实现类上 (list是个接口 如果你要new必须要有个实现类)
将上面一二点 汇聚成一段Java代码:
public interface List<E> extends Collection<E>
这段代码位于java.util.List.java类中 是包含所有List调用的方法
目前已知情报汇总:
(一):List是一个接口,而ArrayList是List接口的一个实现类。
(二):ArrayList类继承并实现了List接口。
(三):List接口不能被构造,也就是我们说的不能创建实例对象,但是我们可以为List接口创建一个指向自己的对象引用,而ArrayList实现类的实例对象就在这充当了这个指向List接口的对象引用。
所以现在我应该要来弄清楚实现List接口的对象 \"ArrayList\"
第二部分:何为ArrayList
翻阅 JDK api 我找到了关于ArrayList继承关系的结构
观察继承关系 得出如下结论:
(一):ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
(二):ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。稍后,我们会比较List的“快速随机访问”和“通过Iterator迭代器访问”的效率。
(三):ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
(四):ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。
继续看下去 JDK API中开头有一段对ArrayList的描述
翻译:
列表接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括空元素。除了实现列表接口之外,这个类还提供了一些方法来操作内部用于存储列表的数组的大小。(这个类大致相当于vector,只是它不同步。) 这里的不同步指的是线程不同步和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。 关于list线程不同步的测试代码 地址:https://www.cnblogs.com/WuXuanKun/p/5556999.html (感谢这位仁兄的博客)
对上面的小总结的一个汇合结论 :
ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它 提供了相关的添加、删除、修改、遍历等功能。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。 此外 ArrayList支持序列化,能通过序列化去传输. ArrayList中的操作不是线程安全的
第三部分 代码示例
第一步在Java类里面创建List
List<String> list = new ArrayList<>();
我们调查一下这个new ArrayList 在java.util.ArrayList.java类中 我找到了这样一段代码,如下:
/** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
这便是我们new的真实的ArrayList了 通过注释我们发现 我们new的 Arrayslist 其默认长度为10
继续调查这个 elementData 还是在java.util.ArrayList.java类中 我找到了 关于elementData 的定义
/** * Shared empty array instance used for default sized empty instances. We * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when * first element is added. */ private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access
/** * Increases the capacity of this <tt>ArrayList</tt> instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It\'s already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } }
是不是有种恍然大悟的感jio 原来ArrayList的老祖宗是一个Object的数组而观察DEFAULTCAPACITY_EMPTY_ELEMENTDATA进行的操作我们发现它为上面的Object数组 提供了进行动态操作的能力 这样从JDK源码中,我们验证了我们上面在第二部分的总结里面说到 ArrayLis其实是一个动态数组.
总结:ArrayList底层其实就是一个Object类型的动态数组,并且通过注释也可以得知,我们在进行new操作时其初始化的长度为10。
说了这么多我们来看看list 能使用ArrayList进行那些操作(以往博客的重头戏来了)先看看他为我们提供了那些方法
所下示例代码均来自 博客园仁兄 “西城墨客” 所属博客 地址:https://www.cnblogs.com/epeter/p/5648026.html
目录
- list中添加,获取,删除元素;
- list中是否包含某个元素;
- list中根据索引将元素数值改变(替换);
- list中查看(判断)元素的索引;
- 根据元素索引位置进行的判断;
- 利用list中索引位置重新生成一个新的list(截取集合);
- 对比两个list中的所有元素;
- 判断list是否为空;
- 返回Iterator集合对象;
- 将集合转换为字符串;
- 将集合转换为数组;
- 集合类型转换;
- 去重复;
- List转换MAP
- List分组
- List 遍历
1.list中添加,获取,删除元素;
添加方法是:.add(e); 获取方法是:.get(index); 删除方法是:.remove(index); 按照索引删除; .remove(Object o); 按照元素内容删除;
List<String> person=new ArrayList<>(); person.add(\"jackie\"); //索引为0 //.add(e) person.add(\"peter\"); //索引为1 person.add(\"annie\"); //索引为2 person.add(\"martin\"); //索引为3 person.add(\"marry\"); //索引为4 person.remove(3); //.remove(index) person.remove(\"marry\"); //.remove(Object o) String per=\"\"; per=person.get(1); System.out.println(per); ////.get(index) for (int i = 0; i < person.size(); i++) { System.out.println(person.get(i)); //.get(index) }
View Code
2.list中是否包含某个元素;
方法:.contains(Object o); 返回true或者false
List<String> fruits=new ArrayList<>(); fruits.add(\"苹果\"); fruits.add(\"香蕉\"); fruits.add(\"桃子\"); //for循环遍历list for (int i = 0; i < fruits.size(); i++) { System.out.println(fruits.get(i)); } String appleString=\"苹果\"; //true or false System.out.println(\"fruits中是否包含苹果:\"+fruits.contains(appleString)); if (fruits.contains(appleString)) { System.out.println(\"我喜欢吃苹果\"); }else { System.out.println(\"我不开心\"); }
View Code
3.list中根据索引将元素数值改变(替换);
注意 .set(index, element); 和 .add(index, element); 的不同;
String a=\"白龙马\", b=\"沙和尚\", c=\"八戒\", d=\"唐僧\", e=\"悟空\"; List<String> people=new ArrayList<>(); people.add(a); people.add(b); people.add(c); people.set(0, d); //.set(index, element); //将d唐僧放到list中索引为0的位置,替换a白龙马 people.add(1, e); //.add(index, element); //将e悟空放到list中索引为1的位置,原来位置的b沙和尚后移一位 //增强for循环遍历list for(String str:people){ System.out.println(str); }
View Code
4.list中查看(判断)元素的索引;
注意:.indexOf(); 和 lastIndexOf()的不同;
List<String> names=new ArrayList<>(); names.add(\"刘备\"); //索引为0 names.add(\"关羽\"); //索引为1 names.add(\"张飞\"); //索引为2 names.add(\"刘备\"); //索引为3 names.add(\"张飞\"); //索引为4 System.out.println(names.indexOf(\"刘备\")); System.out.println(names.lastIndexOf(\"刘备\")); System.out.println(names.indexOf(\"张飞\")); System.out.println(names.lastIndexOf(\"张飞\"));
View Code
5.根据元素索引位置进行的判断;
if (names.indexOf(\"刘备\")==0) { System.out.println(\"刘备在这里\"); }else if (names.lastIndexOf(\"刘备\")==3) { System.out.println(\"刘备在那里\"); }else { System.out.println(\"刘备到底在哪里?\"); }
View Code
6.利用list中索引位置重新生成一个新的list(截取集合);
方法: .subList(fromIndex, toIndex); .size() ; 该方法得到list中的元素数的和
List<String> phone=new ArrayList<>(); phone.add(\"三星\"); //索引为0 phone.add(\"苹果\"); //索引为1 phone.add(\"锤子\"); //索引为2 phone.add(\"华为\"); //索引为3 phone.add(\"小米\"); //索引为4 //原list进行遍历 for(String pho:phone){ System.out.println(pho); } //生成新list phone=phone.subList(1, 4); //.subList(fromIndex, toIndex) //利用索引1-4的对象重新生成一个list,但是不包含索引为4的元素,4-1=3 for (int i = 0; i < phone.size(); i++) { // phone.size() 该方法得到list中的元素数的和 System.out.println(\"新的list包含的元素是\"+phone.get(i)); }
View Code
7.对比两个list中的所有元素;
//两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象
//1.<br>if (person.equals(fruits)) { System.out.println(\"两个list中的所有元素相同\"); }else { System.out.println(\"两个list中的所有元素不一样\"); } //2. if (person.hashCode()==fruits.hashCode()) { System.out.println(\"我们相同\"); }else { System.out.println(\"我们不一样\"); }
View Code
8.判断list是否为空;
//空则返回true,非空则返回false
if (person.isEmpty()) { System.out.println(\"空的\"); }else { System.out.println(\"不是空的\"); }
View Code
9.返回Iterator集合对象;
System.out.println(\"返回Iterator集合对象:\"+person.iterator());
1+0.将集合转换为字符串;
String liString=\"\"; liString=person.toString(); System.out.println(\"将集合转换为字符串:\"+liString);
View Code
11.将集合转换为数组;
System.out.println(\"将集合转换为数组:\"+person.toArray());
View Code
12.集合类型转换;
//1.默认类型 List<Object> listsStrings=new ArrayList<>(); for (int i = 0; i < person.size(); i++) { listsStrings.add(person.get(i)); } //2.指定类型 List<StringBuffer> lst=new ArrayList<>(); for(String string:person){ lst.add(StringBuffer(string)); }
View Code
13.去重复;
List<String> lst1=new ArrayList<>(); lst1.add(\"aa\"); lst1.add(\"dd\"); lst1.add(\"ss\"); lst1.add(\"aa\"); lst1.add(\"ss\"); //方法 1. for (int i = 0; i <lst1.size()-1; i++) { for (int j = lst1.size()-1; j >i; j--) { if (lst1.get(j).equals(lst1.get(i))) { lst1.remove(j); } } } System.out.println(lst1); //方法 2. List<String> lst2=new ArrayList<>(); for (String s:lst1) { if (Collections.frequency(lst2, s)<1) { lst2.add(s); } } System.out.println(lst2);
View Code
完整代码:
package MyTest01; import java.util.ArrayList; import java.util.List; public class ListTest01 { public static void main(String[] args) { //list中添加,获取,删除元素 List<String> person=new ArrayList<>(); person.add(\"jackie\"); //索引为0 //.add(e) person.add(\"peter\"); //索引为1 person.add(\"annie\"); //索引为2 person.add(\"martin\"); //索引为3 person.add(\"marry\"); //索引为4 person.remove(3); //.remove(index) person.remove(\"marry\"); //.remove(Object o) String per=\"\"; per=person.get(1); System.out.println(per); ////.get(index) for (int i = 0; i < person.size(); i++) { System.out.println(person.get(i)); //.get(index) } //list总是否包含某个元素 List<String> fruits=new ArrayList<>(); fruits.add(\"苹果\"); fruits.add(\"香蕉\"); fruits.add(\"桃子\"); //for循环遍历list for (int i = 0; i < fruits.size(); i++) { System.out.println(fruits.get(i)); } String appleString=\"苹果\"; //true or false System.out.println(\"fruits中是否包含苹果:\"+fruits.contains(appleString)); if (fruits.contains(appleString)) { System.out.println(\"我喜欢吃苹果\"); }else { System.out.println(\"我不开心\"); } //list中根据索引将元素数值改变(替换) String a=\"白龙马\", b=\"沙和尚\", c=\"八戒\", d=\"唐僧\", e=\"悟空\"; List<String> people=new ArrayList<>(); people.add(a); people.add(b); people.add(c); people.set(0, d); //.set(index, element) //将d唐僧放到list中索引为0的位置,替换a白龙马 people.add(1, e); //.add(index, element); //将e悟空放到list中索引为1的位置,原来位置的b沙和尚后移一位 //增强for循环遍历list for(String str:people){ System.out.println(str); } //list中查看(判断)元素的索引 List<String> names=new ArrayList<>(); names.add(\"刘备\"); //索引为0 names.add(\"关羽\"); //索引为1 names.add(\"张飞\"); //索引为2 names.add(\"刘备\"); //索引为3 names.add(\"张飞\"); //索引为4 System.out.println(names.indexOf(\"刘备\")); System.out.println(names.lastIndexOf(\"刘备\")); System.out.println(names.indexOf(\"张飞\")); System.out.println(names.lastIndexOf(\"张飞\")); //根据元素索引位置进行的判断 if (names.indexOf(\"刘备\")==0) { System.out.println(\"刘备在这里\"); }else if (names.lastIndexOf(\"刘备\")==3) { System.out.println(\"刘备在那里\"); }else { System.out.println(\"刘备到底在哪里?\"); } //利用list中索引位置重新生成一个新的list(截取集合) List<String> phone=new ArrayList<>(); phone.add(\"三星\"); //索引为0 phone.add(\"苹果\"); //索引为1 phone.add(\"锤子\"); //索引为2 phone.add(\"华为\"); //索引为3 phone.add(\"小米\"); //索引为4 //原list进行遍历 for(String pho:phone){ System.out.println(pho); } //生成新list phone=phone.subList(1, 4); //.subList(fromIndex, toIndex) //利用索引1-4的对象重新生成一个list,但是不包含索引为4的元素,4-1=3 for (int i = 0; i < phone.size(); i++) { // phone.size() 该方法得到list中的元素数的和 System.out.println(\"新的list包含的元素是\"+phone.get(i)); } //对比两个list中的所有元素 //两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象 if (person.equals(fruits)) { System.out.println(\"两个list中的所有元素相同\"); }else { System.out.println(\"两个list中的所有元素不一样\"); } if (person.hashCode()==fruits.hashCode()) { System.out.println(\"我们相同\"); }else { System.out.println(\"我们不一样\"); } //判断list是否为空 //空则返回true,非空则返回false if (person.isEmpty()) { System.out.println(\"空的\"); }else { System.out.println(\"不是空的\"); } //返回Iterator集合对象 System.out.println(\"返回Iterator集合对象:\"+person.iterator()); //将集合转换为字符串 String liString=\"\"; liString=person.toString(); System.out.println(\"将集合转换为字符串:\"+liString); //将集合转换为数组,默认类型 System.out.println(\"将集合转换为数组:\"+person.toArray()); ////将集合转换为指定类型(友好的处理) //1.默认类型 List<Object> listsStrings=new ArrayList<>(); for (int i = 0; i < person.size(); i++) { listsStrings.add(person.get(i)); } //2.指定类型 List<StringBuffer> lst=new ArrayList<>(); for(String string:person){ lst.add(StringBuffer(string)); } } private static StringBuffer StringBuffer(String string) { return null; } }
View Code
14:List转换Map (示例代码来自:https://www.cnblogs.com/yangweiqiang/p/6934671.html) 感谢这位小火纸
随便来个Java类 添加一个List 测试数据
List<Apple> appleList = new ArrayList<>();//存放apple对象集合 Apple apple1 = new Apple(1,\"苹果1\",new BigDecimal(\"3.25\"),10); Apple apple12 = new Apple(1,\"苹果2\",new BigDecimal(\"1.35\"),20); Apple apple2 = new Apple(2,\"香蕉\",new BigDecimal(\"2.89\"),30); Apple apple3 = new Apple(3,\"荔枝\",new BigDecimal(\"9.99\"),40); appleList.add(apple1); appleList.add(apple12); appleList.add(apple2); appleList.add(apple3);
id为key,apple对象为value,可以这么做:ps 此方法只适用于JDK1.8+
/** * List -> Map * 需要注意的是: * toMap 如果集合对象有重复的key,会报错Duplicate key .... * apple1,apple12的id都为1。 * 可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2 */ Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));
15:List分组
List里面的对象元素,以某个属性来分组,例如,以id分组,将id相同的放在一起:
//List 以ID分组 Map<Integer,List<Apple>> Map<Integer, List<Apple>> groupBy = appleList.stream().collect(Collectors.groupingBy(Apple::getId)); System.err.println(\"groupBy:\"+groupBy); {1=[Apple{id=1, name=\'苹果1\', money=3.25, num=10}, Apple{id=1, name=\'苹果2\', money=1.35, num=20}], 2=[Apple{id=2, name=\'香蕉\', money=2.89, num=30}], 3=[Apple{id=3, name=\'荔枝\', money=9.99, num=40}]}
16:list遍历
List<String> list = new ArrayList<String>(); list.add(\"aaa\"); list.add(\"bbb\"); list.add(\"ccc\"); 方法一: 超级for循环遍历 for(String attribute : list) { System.out.println(attribute); } 方法二: 对于ArrayList来说速度比较快, 用for循环, 以size为条件遍历: for(int i = 0 ; i < list.size() ; i++) { system.out.println(list.get(i)); } 方法三: 集合类的通用遍历方式, 从很早的版本就有, 用迭代器迭代 Iterator it = list.iterator(); while(it.hasNext()) { System.ou.println(it.next); }
View Code
第四部分 吹牛
看看窗外的天(完了)
开个玩笑 编程之道莫苦了自己