ArrayList和LinkedList
ArrayList高级equals()方法??判断两个ArrayList对象里面的元素是否全部相等,true(相等)、false(不相等)。 import java.util.ArrayList; import java.util.List; public class TestEquals { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("aaa"); List<String> list2 = new ArrayList<>(); list2.add("AAA"); //false Java区分大小写 System.out.println(list.equals(list2)); } } isEmpty()方法??判断当前的集合是否为空,true(为空)、false(非空)。 import java.util.ArrayList; import java.util.List; public class TestIsEmpty { public static void main(String[] args) { List<String> list1 = new ArrayList<>(); //true:此时没有元素,结果true System.out.println(list1.isEmpty()); List<String> list2 = new ArrayList<>(); list2.add("Tomson"); //false:一旦有元素,则不为空,结果false System.out.println(list2.isEmpty()); } } import java.util.List; public class TestArrayList { public static void main(String[] args) { List<String> list1 = new ArrayList<>(); // List<String> list = null; /* Exception in thread "main" java.lang.NullPointerException at com.whsxt.day6.arraylist.advance.TestArrayList.main(TestArrayList.java:10) */ // 没有创建对象,就调用成员方法会出现:NullPointerException // 也就是说:list为null,然后调用成员方法,抛出NullPointerException // System.out.println(list.isEmpty()); // 避免出现空指针异常,我们经常使用一下方式代替isEmpty()方法 if(null == list || list.size()==0) { System.out.println("is empty"); }else { System.out.println("不是空集合,可以对ArrayList做操作"); } } } ??小结:isEmpty()方法会抛出NullPointerException,所以工作中使用 null == list || list.size()==0 来代替。 clear()方法??清空集合元素,但不会释放集合的内存。 在工作中clear()方法一般用于清空购物车。 import java.util.ArrayList; import java.util.List; public class TestArrayListClear { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Tom"); list.add("Tom"); list.add("Tom"); list.add("Tom"); list.add("Tom"); System.out.println(list.size()); // 调用该方法,回将ArrayList里面的数组所有的元素设置为null,但是不会释放ArrayList对象占用的内存,也就是说ArrayList这个对象还在 list.clear(); System.out.println("After="+list.size()); } } indexOf()方法??返回某个元素在集合中的下标(索引),如果该元素在集合中不存在返回 -1。 import java.util.ArrayList; import java.util.List; public class TestArrayListIndexOf { /** * 创建集合对象,向集合添加元素 * 调用indexOf()方法,传入参数,判断参数是否在集合中存在 * @param args */ public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Tom"); list.add("Jim"); list.add("Sam"); int index = list.indexOf("Sam"); // 2 //int index = list.indexOf("Jerry"); // -1 System.out.println(index); } } addAll()方法??将一个集合(A)的数据,加入到另一个集合(B)中。 import java.util.ArrayList; import java.util.List; public class TestArrayListAddAll { public static void main(String[] args) { List<String> list1 = new ArrayList<>(); List<String> list2 = new ArrayList<>(); list1.add("Tomson"); list2.add("Jerry"); list2.add("Jason"); // 将list1集合的数据加入到list2中 // addAll(Collection<? extends String>) 型参是父接口,实参可以传入子接口 // 放入集合中的数据必须是String或者String的子类 // 也就是说list1集合里面的数据必须是String或者String的子类(但是String没有子类,所以只能放String) list2.addAll(list1); System.out.println(list2); } } 数组集合之间的转换asList():数组转集合??定义一个数组,然后转换为 ArrayList 集合。 import java.util.Arrays; import java.util.List; /** * 数组转换为集合 */ public class TestArrayToArrayList { public static void main(String[] args) { String[] arrs= {"Adam","Jackson","Martin"}; List<String> list = Arrays.asList(arrs); System.out.println(list); } } import java.util.Arrays; import java.util.List; /** * 数组转换为集合 */ public class TestArrayToArrayList { public static void main(String[] args) { // int[] arrs = {10,20,40}; // 错误(不能使用基本类型的数据) Integer[] arrs = {10,40}; // list编译期是java.util.List类型的对象 // list运行期是java.util.Arrays.ArrayList,该类型没有add()方法,所以程序运行抛出UnsupportedOperationException异常 List<Integer> list = Arrays.asList(arrs); // UnsupportedOperationException:不支持add()方法所以抛出异常 // list.add(50); // list.remove(2); System.out.println(list.size()); } } toArray():集合转数组import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** *集合转数组 */ public class TestListToArray { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Tomson"); list.add("Jackson"); list.add("Jason"); //将集合转换为Object类型数组 Object[] objArray = list.toArray(); System.out.println(Arrays.toString(objArray)); //如何将集合转换为String[]; String [] arrs =new String[list.size()]; //toArray(T[])型参是泛型数组,实参可以是类型明确的数组 //将arrs作为实参传入到toArray(T[])方法中,然后list将里面的元素填充到arrs数组 list.toArray(arrs); for(String str:arrs) { System.out.println(str); } } } 遍历ArrayList集合??遍历:访问集合中的每个元素。 import java.util.ArrayList; import java.util.List; import java.util.Iterator; /** * 遍历集合 */ public class TestIterator { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("tom1"); list.add("tom2"); list.add("tom3"); list.add("tom4"); list.add("tom5"); // 使用 for 循环,访问集合的每个元素 for (int i = 0; i < list.size(); i++) { // 根据下标获取集合的元素 String name = list.get(i); System.out.println(name); } // 使用 foreach 循环,访问集合的每个元素,不用使用下标遍历 // 从list集合里面获取每一个元素,将元素存储到变量name里面 // 由于没有下标,并且for循环的list只会执行一次,所以比for循环效率高 // : --> in for (String name : list) { System.out.println(name); } // 使用 Iterator(迭代器)访问集合每个元素 // it.hasNext():判断有没有元素,true有元素(进入循环体)、false没有元素 for(Iterator<String> it = list.iterator();it.hasNext();) { //获取元素 String name = it.next(); System.out.println("name="+name); } } } 其他方法??sort() 对集合中的元素排序。 ??subList(beginIndex,endIndex):根据开始索引和结束索引获取子集合的数据,数据取值范围 [beginIndex,endIndex) 。 ?降序排序 [1,10,5,8,30,25] import java.util.ArrayList; import java.util.List; public class TestArrayListSort { public static void main(String[] args) { List<Integer> list = new ArrayList<>(); list.add(1); list.add(0); list.add(10); list.add(20); list.add(18); /* list.sort(new Comparator<Integer>() { @Override public int compare(Integer o1,Integer o2) { return o1.compareTo(o2); } });*/ // 使用lambda实现 list.sort((o1,o2) -> o1.compareTo(o2)); System.out.println(list); // 根据开始索引和结束索引获取子集合的数据 List<Integer> subList = list.subList(1,3); subList.remove(0); System.out.println(subList); } } LinkedList??双向链表:每个节点都有自己的前驱节点和后继节点 ??ArrayList是数组结构(线性),LinkedList是一个链表结构 LinkedList存储机制public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>,Deque<E>,Cloneable,java.io.Serializable { transient int size = 0; /** * 指向LinkedList的首部节点 */ transient Node<E> first; /** * 指向LinkedList的尾部节点 */ transient Node<E> last; //Node是LinkedList的静态内部类 //添加的元素全部放入Node对象 private static class Node<E> { // E Element 存储对象的 // list.add(10); 此时10会存储到E item里面 E item; // 当前节点的后继节点 Node<E> next; // 当前节点的前驱节点 Node<E> prev; Node(Node<E> prev,E element,Node<E> next) { this.item = element; this.next = next; this.prev = prev; } } /* 将新元素添加到链表的末尾 */ public boolean add(E e) { linkLast(e); return true; } /** * Links e as last element. * 将e连接到链表的最后一个元素 * [10,8] * 需要将新节点9添加到集合 */ void linkLast(E e) { // last存储了添加新节点之前最后一个元素 Node=8 // l是一个局部变量,存储当前的最后一个节点信息 Node =8 final Node<E> l = last; // 创建新节点对象Node=9,设置新节点的前驱节点 Node =8 final Node<E> newNode = new Node<>(l,e,null); // 新节点创建完毕,新节点9就是LinkedList的最后一个节点 last = newNode; // 条件成立:新节点是第一个节点 // 条件不成立:将倒数第二个节点8的后继节点(next),指向新节点9 if (l == null) first = newNode; else //是指新节点的后继节点 l.next = newNode; size++; modCount++; } } ?删除元素:只需要将当前节点(元素)的前驱节点和后继节点的关系解除,JVM帮你删除 LinkedList常用方法??boolean add(E): 新元素添加到集合的末尾 ??boolean offer(E): 新元素添加到集合末尾 ??add():返回类型boolean import java.util.LinkedList; /** * 新元素添加到集合末尾 */ public class TestLinkedListOffer { public static void main(String[] args) { LinkedList<Integer> list = new LinkedList<>(); list.offer(133); list.offer(132); list.offer(138); //[133,132,138] System.out.println(list); } } ??get(int index):根据下标获取元素 ??peek():获取首部元素 ??区别:如果集合没有元素peek()相关方法返回null,get()相关方法抛出异常NoSuchElementException import java.util.LinkedList; /** * peek()相关方法和get()相关方法都是获取元素 * 区别:如果集合没有元素peek()相关方法返回null,get()相关方法抛出异常NoSuchElementException */ public class TestLinkedListPeek { public static void main(String[] args) { LinkedList<Integer> list = new LinkedList<>(); list.offer(133); list.offer(132); list.offer(138); Integer num = list.peekFirst(); Integer num2=list.peekLast(); //peek():返回集合首部元素 Integer num3 = list.peek(); System.out.println("first="+num); System.out.println("last="+num2); System.out.println("first="+num3); } } ??remove(int index):根据下标删除元素 ??poll():删除首部元素 ??区别:LinkedList集合没有元素的情况下,调用remove()相关方法删除元素会抛出NoSuchElementException,poll()相关方法会返回null。 ??共性:不管是remove()相关的方法还是poll()相关的方法,它们都是删除集合中的元素,会将删除的元素作为返回值。 LinkedList实现队列(queue)??队列:一个元素挨着一个元素 ???入队:offerLast() ???出队:pollFirst() ??特征:==先进先出== ?【工作中经常使用于电商项目:提交订单会将购买信息放入到服务器的队列中(入队), 服务器处理你的订单(出队)。】 ? ?例:输入同学姓名,输入Q结束(使用栈完成) import java.util.LinkedList; /** * 自定义队列 * 使用LinkedList实现的 */ public class TestQueue { /** * 队列的本质是一个LinkedList */ private LinkedList<String> queue = new LinkedList<>(); /** * 入队 * @param element 入队的元素 */ public void push(String element) { queue.offerFirst(element); } /** * 元素出队列,删除队列首部元素,返回删除的结果 * @return 删除的结果 */ public String poll() { return queue.pollLast(); } /** * 队列非空的情况下出队 * 出队列之前需要调用该方法进行判断,如果队列为空,不会调用出队列的方法poll() * @return true 队列非空 false队列为空 */ public boolean isNotEmpty() { return !(null == queue || queue.size()==0); } } import java.util.Scanner; /** * 测试入队和出队 * 场景:输入同学姓名,输入Q结束,入队列 offerLast 新元素添加到集合末尾 [Tom,Jerry,Martin,Adam,Robert] * 打印同学的姓名 出队列 pollFirst [Tom,Robert] * 前提:非空的情况下才能出队列 */ public class TestQueue { /** * 步骤: * 1创建队列 * 2使用循环:输入姓名,没有输入Q的情况下,一直入队,一旦输入Q停止入队 * 3使用循环:队列非空的情况下出队 * @param args */ public static void main(String[] args) { try(Scanner input = new Scanner(System.in);){ J0812Queue queue = new J0812Queue(); System.out.println("请输入学生姓名,输入Q结束"); //入队 while(true) { String name = input.nextLine(); //条件成立:停止入队 if("Q".equalsIgnoreCase(name)) { break; } queue.push(name); } //出队 while(queue.isNotEmpty()) { String name = queue.poll(); System.out.print(name+" "); } }catch(Exception e) { System.err.println("队列操作失败"); e.printStackTrace(); } } } LinkedList实现栈??特征:先进后出 ,后进先出(类似于弹夹进出子弹) ????入栈:offerLast() ???出栈:pollLast() /** * 入栈 * @param element 入栈的元素 */ public void push(String element) { queue.offerLast(element); } /** * 元素出栈,删除栈尾部元素,返回删除的结果 * @return 删除的结果 */ public String poll() { return queue.pollLast(); } ArrayList和LinkedList区别??1、ArrayList本质是一个数组,LinkedList本质是一个链表 ArrayList和LinkedList单元测试(20W的压力)
总体:ArrayList 性能高于LinkedList 小结:经常遍历集合中的元素使用 ArrayList ??经常需要插入和删除集合中的元素使用 LinkedList import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.junit.Test; /** * ArrayList add get remove 20W * LinkedList add get remove 20W */ public class TestArrayListAndLinkedList { private List<Integer> arrayList = new ArrayList<>(3000); private List<Integer> linkedList = new LinkedList<>(); private final static int SIZE = 200000; /** * 3.67ms */ @Test public void testArrayListAdd() { for(int i=0;i<SIZE;i++) { arrayList.add(i); } System.out.println(arrayList.size()); } /** * 2ms */ @Test public void testLinkedListAdd() { for(int i=0;i<SIZE;i++) { linkedList.add(i); } System.out.println(linkedList.size()); } /** * 测试ArrayList的get方法20W * 1. 调用add方法添加元素到集合 * 2. 使用for循环get20W次 * 耗时3.33ms */ @Test public void testArrayListGet() { this.testArrayListAdd(); for(int i=0;i<SIZE;i++) { arrayList.get(i); } } /** * 测试LinkedList的get方法20W * 1. 调用add方法添加元素到集合 * 2. 使用for循环get20W次 * 耗时14.6秒 */ @Test public void testLinkedListGet() { this.testLinkedListAdd(); for(int i=0;i<SIZE;i++) { linkedList.get(i); } } /** * 测试ArrayListremove20W * 1. 调用add方法添加元素到集合 * 2. 使用for循环删除ArrayList首部元素 * 耗时1.72秒 */ @Test public void testArrayListRemove() { this.testArrayListAdd(); for(int i=0;i<SIZE;i++) { arrayList.remove(0); } } /** * 测试LinkedList remove20W * 1. 调用add方法添加元素到集合 * 2. 使用for循环删除LinkedList首部元素 * 耗时6.33ms */ @Test public void testLinkedListRemove() { this.testLinkedListAdd(); for(int i=0;i<SIZE;i++) { linkedList.remove(0); } } } ArrayList的排序??1、Comparable 内部比较器 ??2、Comparator 外部比较器 ??3、Collator 汉字按照拼音排序 ??4、Collections.reverSEOrder(Comparator); 降序排序 ?需要:Collections工具类的sort()方法 ?还需要:Comparable和Comparator比较器 ?Comparable 内部比较器,实体类通常实现该接口来制定比较规则,也是一个默认的比较规则。 ?Comparator 外部比较器,也是一个比较工具的接口 。 场景:定义一个ArrayList集合,里面存储了若干个Student类型的对象{id,stuName,stuAge,stuScore} 问题1:默认按照id排序 步骤:1. 定义Student类型,实现Comparable接口 public class Student implements Comparable<Student> { private int id; private String stuName; private int stuAge; /** * 学生成绩 */ private int stuScore; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public int getStuAge() { return stuAge; } public void setStuAge(int stuAge) { this.stuAge = stuAge; } public int getStuScore() { return stuScore; } public void setStuScore(int stuScore) { this.stuScore = stuScore; } public Student() {} public Student(int id,String stuName,int stuAge,int stuScore) { this.id = id; this.stuName = stuName; this.stuAge = stuAge; this.stuScore = stuScore; } @Override public String toString() { return "Student [id=" + id + ",stuName=" + stuName + ",stuAge=" + stuAge + ",stuScore=" + stuScore + "]"; } /** *Comparable比较器实现的方法,我们在此自定义比较的规则 *对id进行比较 */ @Override public int compareTo(Student o) { /* if( this.getId()>o.getId()){ return 1; }else if(this.getId()<o.getId()) { return -1; }else { return 0; } */ return this.getId() - o.getId(); } } import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * 创建ArrayList对象,将Student添加到ArrayList,将其按照id排序,最后打印排序结果 */ public class TestStudentSort { private final static List<Student> STUDENT_LIST = new ArrayList<>(); static { STUDENT_LIST.add(new Student(19,"Sam",18,39)); STUDENT_LIST.add(new Student(13,"Merry",16,79)); STUDENT_LIST.add(new Student(14,"Terry",31,89)); STUDENT_LIST.add(new Student(18,"Carry",69)); STUDENT_LIST.add(new Student(29,"Jerry",19,59)); STUDENT_LIST.add(new Student(15,"Herry",17,49)); } public static void main(String[] args) { // 将STUDENT_LIST集合排序 // 编译错误:因为没有指定比较的规则,也就是说sort方法进行排序,必须指定比较规则 // Collections.sort(STUDENT_LIST); Collections.sort(STUDENT_LIST); // 遍历集合元素 for(Student stu : STUDENT_LIST) { System.out.println(stu); } } } ?注意:排序必须要指定比较规则(可以用Comparable和Comparator来指定). 问题2:从控制台输入整数【1按照id排序,2按照年龄排序,3按照成绩排序,4按照姓名排序】 import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Scanner; /** * 创建ArrayList对象,将Student添加到ArrayList,将其按照id排序,最后打印排序结果 */ public class TestStudentSort2 { private final static List<Student> STUDENT_LIST = new ArrayList<>(); static { STUDENT_LIST.add(new Student(19,"刘大","陈二","张三","李四",21,"王五","赵六",49)); } /** * 步骤:1. 从控制台输入整数 * 2. 编写switch语句 * 3. 根据客户输入整数进行对应的排序策略 * @param args */ public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("请输入整数1按照id排序2按照年龄排序3按照成绩排序4按照姓名排序"); switch (input.nextInt()) { case 1: Collections.sort(STUDENT_LIST); break; case 2: // 匿名内部类实现 Collections.sort(STUDENT_LIST,new Comparator<Student>() { @Override public int compare(Student o1,Student o2) { return o1.getStuAge()-o2.getStuAge(); } }); break; case 3: // lambda实现 Collections.sort(STUDENT_LIST,(o1,o2)->o1.getStuScore()-o2.getStuScore()); break; case 4: Collections.sort(STUDENT_LIST,o2)->o1.getStuName().compareTo(o2.getStuName())); break; default: System.out.println("输入错误,程序退出"); break; } //遍历集合元素 for(Student stu : STUDENT_LIST) { System.out.println(stu); } } } 中文排序import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Locale; import java.util.Scanner; /** * 创建ArrayList对象,将Student添加到ArrayList,将其按照id排序,最后打印排序结果 */ public class TestStudentSort2 { private final static List<Student> STUDENT_LIST = new ArrayList<>(); static { STUDENT_LIST.add(new Student(19,"王五一",41)); } /** * 步骤:1. 从控制台输入整数 * 2. 编写switch语句 * 3. 根据客户输入整数进行对应的排序策略 * @param args */ public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("请输入整数1按照id排序2按照年龄排序3按照成绩排序4按照姓名排序"); switch (input.nextInt()) { case 1: Collections.sort(STUDENT_LIST); break; case 2: Collections.sort(STUDENT_LIST,Student o2) { return o1.getStuAge()-o2.getStuAge(); } }); break; case 3: //Collections.sort(STUDENT_LIST,o2)->o1.getStuScore()-o2.getStuScore()); //使用降序对成绩进行排序 //代码可读性不佳 //Collections.sort(STUDENT_LIST,o2)->-(o1.getStuScore()-o2.getStuScore())); //Collections.reverSEOrder(cmp) 将集合中的元素进行反转排序 Collections.sort(STUDENT_LIST,Collections.reverSEOrder((o1,o2)->o1.getStuScore()-o2.getStuScore())); break; case 4: /* // Collections.sort(STUDENT_LIST,o2)->o1.getStuName().compareTo(o2.getStuName())); // 对汉字进行排序(按照拼音排序) Collections.sort(STUDENT_LIST,new Comparator<Student>() { // 1.创建Collator对象 // 2.调用该对象的compare(o1,o2)方法进行排序 @Override public int compare(Student o1,Student o2) { // 创建Collator对象 此类来构建自然语言文本的搜索和排序例程 // Collator collator = Collator.getInstance(); Collator collator = Collator.getInstance(Locale.CHINA); return collator.compare(o1.getStuName(),o2.getStuName()); } }); Collections.sort(STUDENT_LIST,o2) -> { Collator collator = Collator.getInstance(); return collator.compare(o1.getStuName(),o2.getStuName()); }); //Collator实现类Comparator接口,所以你首先要创建Collator类型的对象 //然后调用compare(str1,str2)方法,参数就是你要指定的字符串比较规则 */ Collections.sort(STUDENT_LIST,o2)->Collator.getInstance(Locale.CHINA).compare(o1.getStuName(),o2.getStuName())); break; default: System.out.println("输入错误,程序退出"); break; } //遍历集合元素 for(Student stu : STUDENT_LIST) { System.out.println(stu); } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |