package collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* java集合框架
*
* java.util.Collection是所有集合的顶级接口
* 集合与数组一样,可以保存一组元素,并且提供了操作元素的相关方法,使用更方便
* Collection下面有两个常见的子接口:
* java.util.List: 线性表,可以保存重复元素并且有序,可以通过下标操作。
* java.util.Set: 不可重复的集合
*
* List常见的实现类:
* java.util.ArrayList、java.util.LinkedList
* Set常见的实现类:
* java.util.HashSet
*
*
* @author YanLy
* @date 2021/6/2 16:05
*/
public class CollectionDemo1 {
public static void main(String[] args) {
Collection c = new ArrayList();
/*
boolean add(E e):向当前集合中添加一个元素,成功添加后返回true,否则返回false。
*/
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
System.out.println(c);
// [one, two, three, four, five] 重写了toString方法
/*
int size():返回当前集合的元素个数
*/
int size = c.size();
System.out.println("size:"+size);// size:5
/*
boolean isEmpty():判断当前集合是否为空集(不含有任何元素)
*/
boolean isEmpty = c.isEmpty();
System.out.println("是否为空集:"+isEmpty); // false
/*
clear() :一次性清空集合中的所有元素
*/
c.clear(); // 清空集合
System.out.println(c); // []
System.out.println(c.isEmpty()); // true
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
/**
* 集合与元素equals相关的操作
* 集合有些操作是依靠元素的equals方法进行的,因此要妥善的重写元素的equals方法。
*
* @author YanLy
* @date 2021/6/2 16:28
*/
public class CollectionDemo2 {
public static void main(String[] args) {
// Collection c = new ArrayList();
Collection c = new HashSet(); // 不可以存放重复元素
c.add(new Point(1,2));
c.add(new Point(3,4));
c.add(new Point(5,6));
c.add(new Point(7,8));
c.add(new Point(9,10));
// 集合重写了toString方法,
// 格式为:[元素1.toString(),元素2.toString()...]
System.out.println(c); // [(1,2), (3,4), (5,6), (7,8), (9,10)]
/*
boolean contains(Object o)
判断集合是否包含给定元素,
判断依据是 看给定元素是否存在 与集合元素equals比较为true的情况,存在则认为包含
*/
Point p = new Point(1,2);
boolean contains = c.contains(p);
System.out.println("是否包含:" + contains); // true
/*
remove() 是从集合中删除给定元素,删除也是删除与给定元素equals比较为true的元素,
如果集合中存在多个重复的元素,那么仅删除第一个。
*/
boolean b = c.add(p);// 将p对象存入到集合c,对于Set集合而言,重复元素无法再次存入。
System.out.println("添加是否成功"+b); // false
c.remove(p);
System.out.println(c); // [(3,4), (5,6), (7,8), (9,10)]
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* 集合只能存放引用类型元素,并且存放的是元素的引用(地址值)
*
* @author YanLy
* @date 2021/6/2 17:15
*/
public class CollectionDemo3 {
public static void main(String[] args) {
Collection c = new ArrayList();
// int i =1;
// c.add(i); // 自动转换为包装类
// System.out.println(c);
Point p = new Point(1,2);
c.add(p);
System.out.println("p: "+p); // p: (1,2)
System.out.println("c: "+c); // c: [(1,2)]
p.setX(2); // 因为传递的是地址值,所以p里的值改了 集合里的也改了
System.out.println("p: "+p); // p: (2,2)
System.out.println("c: "+c); // c: [(2,2)]
}
}
package collection; import java.util.ArrayList; import java.util.Collection; /** * 集合之间的操作 * * @author YanLy * @date 2021/6/2 17:21 */ public class CollectionDemo4 { public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("java"); c1.add("c++"); c1.add(".net"); System.out.println("c1:" + c1);//c1:[java, c++, .net] Collection c2 = new ArrayList(); c2.add("android"); c2.add("ios"); c2.add("java"); System.out.println("c2:" + c2);//c2:[android, ios, java] /* boolean addAll(Collection c) 将给定集合中的所有元素添加到当前集合中,当前集合发生了改变就返回true */ c1.addAll(c2); System.out.println("c1:"+c1); // c1:[java, c++, .net, android, ios, java] System.out.println("c2:"+c2); // c2:[android, ios, java] /* boolean containsAll(Collection c) 判断当前集合是否包含给定集合中的所有元素 */ boolean contains = c1.containsAll(c2); System.out.println("是否全部包含:" + contains); // 是否全部包含:true Collection c3 = new ArrayList(); contains = c1.containsAll(c3); System.out.println("是否全部包含:" + contains); // 是否全部包含:true c3.add("c++"); c3.add("android"); c3.add("php"); System.out.println("c3:"+c3); // c3:[c++, android, php] contains = c1.containsAll(c3); System.out.println("是否全部包含:" + contains); // 是否全部包含:false /* removeAll(Collection c) 删除当前集合中与给定集合的共有元素 */ c1.removeAll(c3); System.out.println("c1:"+c1); // c1:[java, .net, ios, java] System.out.println("c3:"+c3); // c3:[c++, android, php] } }
package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
/**
* 集合转换为数组
* Collection 提供了一个方法:toArray().可以将当前集合转换为一个数组
*
* @author YanLy
* @date 2021/6/2 17:37
*/
public class CollectionToArrayDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList(); // <String> 泛型
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
System.out.println("c:"+c); // c:[one, two, three, four, five]
Object[] array = c.toArray();
/*
T[] toArray(T[] array)
将当前集合转换为数组,该方法要求传入一个数组。
如果该数组可用(数组长度 >= 集合的size时),会将当前集合元素存入数组后再将该数组返回。
如果不可用,会创建一个与参数数组同类型并且长度与集合size一致的数组并将元素存入后返回。
*/
System.out.println(array.length); // 5
System.out.println(Arrays.toString(array)); // [one, two, three, four, five]
String[] arr = c.toArray(new String[c.size()]);
System.out.println(arr.length); // 5
System.out.println(Arrays.toString(arr)); // [one, two, three, four, five]
arr = c.toArray(new String[9]);
System.out.println(arr.length); // 9
System.out.println(Arrays.toString(arr));
// [one, two, three, four, five, null, null, null, null]
arr = c.toArray(new String[0]); //new String[-1]: NegativeArraySizeException
System.out.println(arr.length); // 5
System.out.println(Arrays.toString(arr)); // [one, two, three, four, five]
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 集合的遍历
* Collection 提供了一个方法:Iterator iterator()
* 该方法会返回一个用于遍历当前集合的迭代器实现类,使用它可以对集合进行遍历。
* 不同的集合实现类都提供了一个用于遍历自身的迭代器实现类,但是我们不需要。指定它们的名字,
* 用多态的思想把它们看成Iterator 进行操作即可。
*
* java.util.Iterator : 迭代器接口
* 迭代器接口中规定了遍历集合元素所需要的相关方法,使用迭代器遍历需要遵循的原则为:
* 问、取、删,其中删除元素不是遍历过程的必要操作。
*
* @author YanLy
* @date 2021/6/4 10:31
*/
public class IteratorDemo {
public static void main(String[] args) {
// Collection c = new ArrayList();
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("three");
c.add("#");
c.add("four");
c.add("#");
c.add("five");
System.out.println(c); // [one, #, two, #, three, #, four, #, five]
// 获取遍历该集合的迭代器
// Iterator<String> it = c.iterator();
Iterator it = c.iterator();
// 问: boolean hasNext() -- 判断集合是否还有元素可以迭代
while(it.hasNext()){
// 取: E next() -- 获取集合下一个元素(第一次调用时获取第一个,以此类推)
String str = (String)it.next();
// String str = it.next();
System.out.println(str);
if ("#".equals(str)){
// 迭代器要求遍历的过程中不得通过集合的方法增删元素,否则会抛出异常
// c.remove(str); // ConcurrentModificationException 实时修改异常
// 删: remove() -- 迭代器的remove()删除本次遍历出来的元素
// 迭代器 next() 是有记忆的,可以把当前取到的元素获取到 然后进行删除
it.remove();
}
}
System.out.println(c); // [one, two, three, four, five]
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* JDK5之后推出了一个特性:泛型
* 泛型也称参数化类型,允许我们在使用一个类时通过其定义的泛型来指定其属性、方法的参数或返回值的类型。
* 泛型在集合中被广泛使用,用来指定集合中的元素类型。
* 泛型的类型必须是引用类型,有泛型支持的类在使用时如果不指定泛型的具体类型,则默认为原型 Object
*
* @author YanLy
* @date 2021/6/4 11:12
*/
public class Generics {
public static void main(String[] args) {
/*
Collection<E>
Collection接口声明时使用了一个泛型E,那么在定义一个Collection类型的变量时可以指定这个E的实际类型
*/
Collection<String> c = new ArrayList<>();// 指定E为String类型
Collection<String> c1 = new ArrayList();// 后面<>可以省略,前面指定就可以了
// boolean add(E e) 参数类型使用的是Collection上声明的泛型E
c.add("one");//此时编译器认为参数E应当是String类型
c.add("two");
c.add("three");
// c.add(4); // 传入的实参类型与泛型不匹配,编译报错,编译不通过
/*
迭代器也支持泛型,指定的泛型要与其遍历的集合指定的泛型一致
*/
Iterator<String> it = c.iterator();
while(it.hasNext()){
// 编译器在编译时会根据泛型指定的类型补上造型的代码:
// String str = (String)it.next();
String str = it.next();
System.out.println(str);
}
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
/**
* JDK5之后推出了一个特性: 增强型for循环
* 也称新循环,使得我们可以使用相同的语法遍历集合或数组。
* 语法:
* for(元素类型 变量名 :集合或数组){
* 循环体
* }
*
* @author YanLy
* @date 2021/6/4 11:29
*/
public class NewForDemo {
public static void main(String[] args) {
String[]array = {"one","two","three","four","five"};
// for循环
for (int i = 0; i < array.length; i++) {
String str = array[i];
System.out.println(str);
}
System.out.println("-----------------------");
/*
新循环的语法是编译器认可的,而不是虚拟机,
编译器在编译源代码时发现使用新循环遍历数组时,会将代码改成普通的for循环进行。
*/
for (String str:array) {
System.out.println(str);
}
System.out.println("-----------------------");
Collection<String> c = new ArrayList<>();
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
/*
新循环遍历集合时会被编译器改为迭代器遍历。
因此,在使用新循环遍历过程中,仍然不能通过集合的方法增删元素。
*/
for(String str:c){
System.out.println(str);
}
System.out.println("-----------------------");
}
}
package collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* java.util.List接口
* List 继承自 Collection,是可重复的集合,并且有序,提供了一套可以通过下标操作元素的方法。
*
* 常用实现类:
* java.util.ArrayList:内部使用数组实现,查询性能更好
* java.util.LinkedList:内部使用链表实现,增删元素性能更好
*
* @author YanLy
* @date 2021/6/4 11:46
*/
public class ListDemo1 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list); // [one, two, three, four, five]
/*
E get(int index) : 获取当前集合中指定下标处对应的元素
*/
String str = list.get(0); // 获取集合中的第一个元素
System.out.println(str); // one
System.out.println("-------------");
// for循环遍历list集合
for (int i = 0; i < list.size(); i++) {
str = list.get(i);
System.out.println(str);
}
System.out.println("-------------");
for (String str1:list) {
System.out.println(str1);
}
System.out.println("-------------");
/*
E set(int index,E e)
将给定元素设置到指定位置,返回值为该位置原来对应的元素,相当于替换操作
*/
String old = list.set(1,2+"");
System.out.println(list); // [one, 2, three, four, five]
System.out.println("被替换掉的是:" + old); // 被替换掉的是:two
/*
中午作业:在不创建新集合的前提下,将集合元素反转
提示:使用get set方法即可
*/
List<String> list2 = new ArrayList();
list2.add("one");
list2.add("two");
list2.add("three");
list2.add("four");
list2.add("five");
System.out.println(list2);// [one, two, three, four, five]
for (int i = 0; i < list2.size()/2; i++) {
String sub = list2.get(i);
sub = list2.set(list.size()-i-1,sub);
list2.set(i,sub);
}
System.out.println(list2); // [five, four, three, two, one]
/*
集合的反转:
*/
// 在不创建新集合的前提上,将集合元素反转。提示:使用get/set方法实现
for (int i = 0;i<list.size()/2;i++){
// 获取前面位置上的元素
String s = list.get(i);
// 将前面位置上的元素放到后面倒数位置
s = list.set(list.size()-1-i,s);
// 将原倒数位置上的元素放到前面位置上
list.set(i,s);
}
System.out.println(list);
/*
面试题:Collection 和 Collections 的区别?
Collection 是集合的顶级接口,常用的子接口有List和Set...
Collections 是集合的工具类,里面提供了很多操作集合的方法。比如...
*/
/*
reverse(List list) : 反转集合元素
*/
Collections.reverse(list);
System.out.println(list);
}
}
package collection;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/*
面试题:ArrayList、LinkedList 和 Vector 的区别?
相同点:都是List接口的实现类。
ArrayList(扩容*1.5) 和 Vector(扩容*2) 底层都是动态数组,查询性能好;
LinkedList底层是链表,增删性能好,首尾增删性能最佳。
ArrayList 和 Vector 的区别就是 :
ArrayList 是线程不安全的,Vector 是线程安全的。
Vector中的方法都是同步方法(synchronized),所以ArrayList的执行效率要高于Vector。
*/
/**
* 测试LinkedList
*
* @author YanLy
* @date 2021/6/4 14:18
*/
public class ListDemo2 {
public static void main(String[] args) {
// List<String> list = new LinkedList<>();
LinkedList<String> list = new LinkedList<>();
list.add("one");
list.add("two");
list.addFirst("0"); // 在链表头部添加一个元素
list.addLast("3"); // 在链表尾部添加一个元素
System.out.println(list); // [0, one, two, 3]
/*
LinkedList 的 get 方法实现机制:
比较传入的索引值index与集合长度size/2,
如果是index小,那么从第一个元素开始顺序循环,直到找到为止;
如果是index大,那么从最后一个元素开始倒序循环,直到找到为止。
也就是说,越靠近中间位置的元素,调用get方法遍历的次数越多,效率也就越低,
而且随着集合越来越大,get方法的执行性能也会下降,
因此在使用LinkedList的时候,不建议使用这种方式读取数据。
可以使用getFirst()、getLast()直接获取到集合中的第一个和最后一个元素。
*/
String str = list.get(2);
System.out.println(str); // two
str = list.getFirst();
System.out.println(str); // 0
str = list.getLast();
System.out.println(str); // 3
}
}
package collection;
import java.util.ArrayList;
import java.util.List;
/**
* List提供了一堆重载的 add() 、remove()方法
*
* @author YanLy
* @date 2021/6/4 15:15
*/
public class ListDemo3 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list); // [one, two, three, four, five]
/*
void add(int index,E e) : 将给定元素添加到指定位置,原位置及后续位置的元素顺序向后移动
*/
list.add(2,"3");
System.out.println(list); // [one, two, 3, three, four, five]
// 没有覆盖的效果,把之前的元素向后移了
/*
E remove(int index) : 删除并返回指定位置的元素
*/
String str = list.remove(3);
System.out.println(list); // [one, two, 3, four, five]
System.out.println("被删除的元素: "+str); // 被删除的元素: three
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* List subList(int start,int end)
* 获取当前集合中指定范围内的子集
*
* @author YanLy
* @date 2021/6/4 15:23
*/
public class ListDemo4 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
// for-each 只能获取
// 循环赋值
for (int i = 0; i < 10; i++) {
list.add(i);
}
System.out.println(list); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// 获取 3-7 含头不含尾 [3,8)
List<Integer> subList = list.subList(3,8);
System.out.println(subList); // [3, 4, 5, 6, 7]
// 将子集每个元素扩大10倍
for (int i = 0; i < subList.size(); i++) {
int num = subList.get(i);
num*=10;
subList.set(i,num);
}
System.out.println(subList);
/*
当我们通过一个List集合使用subList()获取到一个子集后,
对这个自己的任何操作就是对原集合这部分元素的操作。
*/
System.out.println(list);
// List<Integer> list1 = new ArrayList<>();
// for (int i = 0; i < subList.size(); i++) {
// int j = subList.get(i);
// list1.add(j*10);
// }
// System.out.println(list1);
/*
删除list集合中的2-8
*/
list.subList(2,9).clear();
System.out.println(list);
}
}
package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 数组转换为集合
* 数组的工具类 Arrays 提供了一个静态方法:asList()
* 可以将一个数组转换为一个List集合
*
* @author YanLy
* @date 2021/6/4 15:52
*/
public class ArrayToList {
public static void main(String[] args) {
String[]arr = {"one","two","three","four","five"};
System.out.println("arr: "+Arrays.toString(arr)); // [one, two, three, four, five]
List<String> list = Arrays.asList(arr);
System.out.println(list.size()); // 5
System.out.println("list: "+list); // list: [one, two, three, four, five]
/*
修改集合现有元素
*/
list.set(1,"2");
System.out.println("list: " +list); // list: [one, 2, three, four, five]
/*
数组转换而来的集合,对该集合元素的操作就是对原数组对应元素的操作
*/
System.out.println("arr: "+Arrays.toString(arr)); // arr: [one, 2, three, four, five]
/*
由于数组是定长的,所以集合会改变元素个数的操作都不支持:
*/
// list.add("six");
// 抛出异常: UnsupportedOperationException 不支持操作异常
/*
如果想对元素进行增删操作,需要自行创建一个集合,然后将原集合元素导入到该集合中即可
所有的集合都支持一个参数类型为 Collection 的构造方法,
该构造方法的作用是创建当前集合的同时包含给定集合中的所有元素。
*/
List<String> list2 = new ArrayList<>(list);
System.out.println(list2); // [one, 2, three, four, five]
list2.add("six");
System.out.println(list2); // [one, 2, three, four, five, six]
}
}
package collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
* Collections 提供了一个静态方法 sort,可以对List集合进行自然排序(从小到大)
*
* @author YanLy
* @date 2021/6/4 16:30
*/
public class SortDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Random ran = new Random();
for (int i = 0; i < 10; i++) {
list.add(ran.nextInt(100));
}
System.out.println("list : "+list); // list : [28, 70, 95, 70, 6, 60, 16, 26, 48, 8]
// list.sort(Integer::compareTo); // 尝试 可以从小到大排序
/*
排序
*/
Collections.sort(list);
System.out.println("list : "+list);// list : [6, 8, 16, 26, 28, 48, 60, 70, 70, 95]
/*
乱序
*/
Collections.shuffle(list);
System.out.println("list : "+list); // list : [48, 70, 16, 26, 28, 6, 8, 70, 60, 95]
/*
sort() 重载
第一个参数为 集合名 第二个参数为 Comparator 接口类型
o2-o1 从大到小
o1-o2 从小到大
*/
Collections.sort(list,((o1,o2) -> o2-o1));
System.out.println(list); // [99, 71, 64, 64, 58, 42, 40, 34, 27, 26]
}
}
package collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 对自定义元素进行排序
*
* @author YanLy
* @date 2021/6/4 16:42
*/
public class SortDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(3, 4));
list.add(new Point(7, 8));
list.add(new Point(1, 5));
list.add(new Point(2, 6));
list.add(new Point(9, 0));
System.out.println(list); // [(3,4), (7,8), (1,5), (2,6), (9,0)]
/*
Collections.sort(List list) 方法要求传入参数集合中的元素类型必须实现 Comparable 接口,
该接口中有一个抽象方法comparableTo,这个方法用来定义元素之间比较的大小规则,
只有实现了这个接口的元素才能利用这个方法比较出大小,从而实现排序操作。
java中有很多常用的类都实现了这个接口,比如String、包装类等等。
当我们调用某个API的时候,它反过来要求我们为其修改其他额外的代码时,
这种现象就是侵入性,侵入性不利于程序后期的维护,在开发中应当尽量避免侵入性。
*/
// Collections.sort(list); // 编译报错,Point没有实现Comparable接口
/*
Collections 提供了一个重载的sort方法,要求再传入一个Comparator "比较器",
该比较器用来为集合元素临时定义一种比较规则,
从而将List集合中的元素通过该比较器定义的比较规则进行排序。
通常可以直接以匿名内部类的形式创建该接口的实现类当作参数。
Comparator接口中的compare方法,两个参数就是要比较的两个元素,
方法的返回值为比较大小的关系:
当返回值 > 0 时,表示 o1 > o2;
当返回值 < 0 时,表示 o1 < o2;
当返回值 = 0 时,表示 o1 = o2;
*/
// Comparator<Point> c = new Comparator<Point>() {
// @Override
// public int compare(Point o1, Point o2) {
// // 自己定义比较规则
// // 根据 x 的大小判断排序
// // o1 - o2 为从小到大 o2 - o1 为从大到小
// return o1.getX()-o2.getX();
// }
// };
// Collections.sort(list,c);
// System.out.println(list); // [(1,5), (2,6), (3,4), (7,8), (9,0)]
// 如果只使用一次,可以当作参数传入进去
Comparator<Point> c;
Collections.sort(list,new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
return o1.getX()-o2.getX();
}
});
System.out.println(list); // [(1,5), (2,6), (3,4), (7,8), (9,0)]
// lambda
Collections.sort(list,(o1,o2)->o1.getX()-o2.getX());
System.out.println(list); // [(1,5), (2,6), (3,4), (7,8), (9,0)]
}
}
package collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 排序字符串
* java中提供的类,如String、包装类都实现了Comparable接口,
* 但是有时候其比较规则不能满足我们的排序需求,
* 我们仍然可以使用重载的sort方法临时提供一种比较规则来进行排序
*
* @author YanLy
* @date 2021/6/4 17:42
*/
public class SortDemo3 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// 英文字符串按照字母的顺序进行排序
list.add("Lisa");
list.add("Tom");
list.add("Rose");
list.add("Jack");
list.add("Jerry");
System.out.println(list); // [Lisa, Tom, Rose, Jack, Jerry]
// 按照首字母排序,如果第一个字母相同,按照第二个字母
Collections.sort(list);
System.out.println(list); // [Jack, Jerry, Lisa, Rose, Tom]
// 对中文排序并不准确 需要重写方法
List<String> list1 = new ArrayList<>();
list1.add("海绵宝宝");
list1.add("小蜗");
list1.add("派大星");
list1.add("章鱼哥");
System.out.println(list1); // [海绵宝宝, 小蜗, 派大星, 章鱼哥]
Collections.sort(list1);
System.out.println(list1); // [小蜗, 派大星, 海绵宝宝, 章鱼哥]
Collections.sort(list1, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// return o1.length()-o2.length(); // 长度由小到大排序
// [小蜗, 派大星, 章鱼哥, 海绵宝宝]
return o2.length()-o1.length(); // 长度由大到小排序
// [海绵宝宝, 派大星, 章鱼哥, 小蜗]
}
});
System.out.println(list1);
/*
面试题:
Comparable接口和Comparator接口的区别?
1. Comparable接口位于java.lang包下;
Comparator接口位于java.util包下.
2. Comparable接口用于比较的方法是compareTo();
Comparator接口用于比较的方法是compare().
3. Comparable属于内部比较器,一个类如果想使用Collections的sort方法进行排序,
必须要实现该接口;
Comparator属于外部比较器,
如果想要进行比较的类没有实现Comparable接口或者已经实现了Comparable接口,
但是提供的比较规则不符合需要,我们也可以使用Comparator接口提供临时的比较规则,
相比之下,Comparator接口更灵活,对程序没有侵入性,耦合度低.
*/
}
}
package collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* JDK8以后,集合提供了一个新的方法:foreach,可以使用lambda表达式遍历集合元素。
*
* @author YanLy
* @date 2021/6/5 11:30
*/
public class ForeachDemo {
public static void main(String[] args) {
Collection c = new ArrayList<>();
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list);
/*
集合中有多少个元素,就会调用该lambda表达式多少次,
而每次调用时 e 表示的就是其中的一个元素
*/
list.forEach(e-> System.out.println(e));
System.out.println("-----------------");
/*
forEach 方法出现的原因:
我们常用的集合,比如ArrayList、LinkedList、HashSet都不是线程安全的,
借助Collections对应的方法:
SynchronizedList()、SynchronizedSet()、SynchronizedCollection()
可以将相应的集合转换为一个并发安全的集合。
但是就算是线程安全的集合,它的 add()、remove()等操作都有Synchronized修饰,
也不会与迭代器互斥。这是因为迭代器是一个单独的对象,不是通过集合自身的方法遍历,
因此无法做到迭代器的方法与集合的方法互斥!
此时就需要自行使用同步块维护迭代器遍历与集合自身操作的互斥,来保证并发安全。
JDK8之后推出的forEach方法,是集合自身的方法,
因此和集合自身的add()、remove()等操作互斥,直接保证了并发安全。
*/
// 将当前集合转换为一个线程安全的集合
List<String>synList = Collections.synchronizedList(list);
/*
当多个线程操作同一集合时,首先应当选用线程安全的集合,
同时遍历时就不应当再使用迭代器,而应当使用forEach方法,
这样操作能做到与增删元素互斥,从而保证并发安全。
*/
synList.add("six");
synList.remove("one");
synList.forEach(e-> System.out.println(e));
}
}
package collection;
import java.util.LinkedList;
import java.util.Queue;
/**
* java.util.Queue 队列接口
* 继承自Collection 所以队列本身也是一种集合
* 队列可以保存一组元素,但是存放元素必须遵循先进先出的原则。
* 常用实现类:
* java.util.LinkedList
*
* @author YanLy
* @date 2021/6/5 14:02
*/
public class QueueDemo {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
/*
boolean offer(E e):入队操作,元素会被追加到队列末尾
*/
queue.offer("one");
queue.offer("two");
queue.offer("three");
queue.offer("four");
queue.offer("five");
System.out.println(queue); // [one, two, three, four, five]
/*
E poll() : 出队操作,获取并删除队列中的队首元素
*/
String str = queue.poll();
System.out.println(str); // one
System.out.println(queue); // [two, three, four, five]
/*
E peek() : 引用队首元素,获取后该元素仍然在队列中
*/
str = queue.peek();
System.out.println(str); // two
System.out.println(queue); // [two, three, four, five]
/*
队列的遍历 遍历后,元素并不会出队
*/
// 1.使用新循环遍历
for (String s:queue) {
System.out.println(s);
}
System.out.println(queue); // [two, three, four, five]
// 2.使用forEach()遍历
queue.forEach(e-> System.out.println(e));
// 使用普通循环进行遍历,用peek() pool() 用不了
while(queue.size()>0){
// 使用pool方法遍历,遍历后元素直接被删除
str = queue.poll();
// 使用peek方法遍历虽然不删除,但是只能获取到队列第一个元素
// str = queue.peek(); // 死循环
System.out.println(str);
}
System.out.println(queue); // []
}
}
package collection;
import java.util.Deque;
import java.util.LinkedList;
/**
* java.util.Deque 双端队列接口
* Deque继承自Queue,特点时队列两端都可以做出入队操作。
* 常用实现类:
* java.util.LinkedList
*
* @author YanLy
* @date 2021/6/5 14:29
*/
public class DequeDemo {
public static void main(String[] args) {
Deque<String> deque = new LinkedList<>();
deque.offer("one");
deque.offer("two");
deque.offer("three");
deque.offer("four");
deque.offer("five");
System.out.println(deque); // [one, two, three, four, five]
// 从队首方向入队
deque.offerFirst("six");
System.out.println(deque); // [six, one, two, three, four, five]
// 从队尾方向入队 -- 与 offer 一致
deque.offerLast("seven");
System.out.println(deque); // [six, one, two, three, four, five, seven]
// 从队首出队 -- 与 poll 一致
String str = deque.pollFirst();
System.out.println(str); // six
System.out.println(deque); // [one, two, three, four, five, seven]
// 从队尾出队
str = deque.pollLast();
System.out.println(str); // seven
System.out.println(deque); // [one, two, three, four, five]
}
}
package collection;
import java.util.Deque;
import java.util.LinkedList;
/**
* 栈结构
* 栈可以保存一组元素,但是存取元素必须遵循先进后出的原则
*
* Deque 双端队列如果从同一侧做出入队操作就实现了栈结构,
* 因此 Deque 也为栈,提供了出入栈方法:push()、pop()
*
* @author YanLy
* @date 2021/6/5 14:43
*/
public class StackDemo {
public static void main(String[] args) {
Deque<String> stack = new LinkedList<>();
stack.push("one");
stack.push("two");
stack.push("three");
stack.push("four");
stack.push("five");
System.out.println(stack); // [five, four, three, two, one]
String str = stack.pop();
System.out.println(str); // five
System.out.println(stack); // [four, three, two, one]
}
}