Collection 集合
集合是用于存储引用数据的容器 集合只能存储引用类型数据,不能存储基本类型数据
如果想要在集合中存储整数,小数字符布尔等数据时需要保存对应的包装类对象
interface Collection
Collection常用集合类
// 创建Collection集合
// Collection是一个接口,需要赋值实现类对象
// <Object> 泛型,向集合中添加数据时,只能添加泛型指定类型的数据
Collection<Object> collection = new ArrayList<>();
// 调用add()方法向集合中添加数据,此方法实际是ArrayList实现类的方法,此为多态
// 可以向集合中添加任意Object类型对象
collection.add("Hello");
collection.add("GIRL");
collection.add("Hello");
collection.add("NO");
// 添加基本类型数据时,隐含自动装箱
collection.add(12487);
collection.add(LocalDateTime.now());
System.out.println(collection); //[Hello, GIRL, Hello, NO, 12487, 2022-11-29T09:43:42.780]
System.out.println(collection.isEmpty()); //false
System.out.println(collection.size()); //6
System.out.println(collection.contains("Hello")); //true
System.out.println(collection.contains("WTF!!")); //false
// 遍历循环collection元素,删除长度大于4的元素
for (Iterator<Object> iterator = collection.iterator(); iterator.hasNext(); ) {
Object next = iterator.next();
if (next.toString().length() > 4) {
iterator.remove(); //迭代删除
}
}
// foreach遍历
/*Iterator<Object> iterator = collection.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}*/
for (Object obj : collection) {
System.out.println(obj);
}
// 删除集合中第一个与参数匹配的元素,并返回Boolean结果
boolean hello = collection.remove("Hello");
System.out.println(collection); //[GIRL, Hello, NO, 12487, 2022-11-29T10:15:14.831]
// 清空集合中的元素
collection.clear();
System.out.println(collection.size()); //0
System.out.println(collection.isEmpty()); //true
interface List extend Collection
// 创建list集合存储String字符串,通过泛型指定元素的类型,List接口赋值实现类对象
List<String> list = new ArrayList<>();
// 向集合中添加数据
list.add("What?");
list.add("Where?");
list.add("When?");
list.add("GO!");
list.add("What?");
// 打印list集合,List集合元素存储顺序与添加顺序一致,允许存储重复数据
System.out.println(list); //[What?, Where?, When?, GO!, What?]
System.out.println(list.size());
System.out.println(list.contains("What?"));
System.out.println(list.isEmpty());
boolean result = list.remove("Where?");
System.out.println(result); //true
System.out.println(list); //[What?, When?, GO!, What?]
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String next = iterator.next();
if (next.length() < 5) {
iterator.remove();
}
}
System.out.println(list); //[What?, When?, What?]
// List集合为每个元素指定了索引值,增加一组针对索引值的操作
// add(index, o) 再list集合index位置添加元素o
list.add(0, "world");
System.out.println(list); //[world, What?, When?, What?]
list.add(0, "good");
System.out.println(list); //[good, world, What?, When?, What?]
// get(index) 返回list集合中 index 索引值的元素
System.out.println(list.get(0)); //good
// for循环遍历list集合的每个元素
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " "); //good world What? When? What?
}
System.out.println();
// set(i, o) 设置list集合中 i 位置的元素为 o
list.set(0, "GOOD");
System.out.println(list); //[GOOD, world, What?, When?, What?]
集合的排序
// sort排序
// 再JDK8中新增了sort(Comparator<? super E> c)排序功能,方法形参Comparator是接口,在调用
// 先定义一类实现Comparator接口,再创建实现类对象
list.sort(new StringCMP());
System.out.println(list); //[GOOD, What?, What?, When?, world]
// 实参可以直接传递Comparator接口的匿名内部类对象
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// 在匿名内部类中重写接口抽象方法,定义一个比较规则
return o2.compareTo(o1); //降序排序
}
});
System.out.println(list); //[world, When?, What?, What?, GOOD]
// 以静态内部类的形式定义Comparator接口的实现类
private static class StringCMP implements Comparator<String> {
// 类重写接口的抽象方法,在该方法中定义一个比较规则
@Override
public int compare(String o1, String o2) {
// 抽象方法compare通过参数接收两个字符串,在方法中比较o1与o2
// 规则1:当 o1 > o2 时返回正数,o1 = o2 时返回0,o1 < o2 时返回负数,对应升序排序
// 规则1:当 o1 > o2 时返回负数,o1 = o2 时返回0,o1 < o2 时返回正数,对应升序排序
return o1.compareTo(o2); // 升序
}
}
集合与数组的转换
// 可以把Collection集合中的数据复制到数组中
/*
* toArray(T[] a),
* 当参数a数组的长度大于等于集合中元素的数量则把集合中的元素复制到参数a数组中;
* 当参数a数组的长度小于集合中元素的数量,则会根据集合中元素的数量创建一个新的数组,把集合中的元素复制到这个新数组中,并返回这个新数组
*/
// 先定义存储数据的数组,数组的长度大于等于集合中的元素的数量
String[] data = new String[list.size()];
// 把list集合中的元素复制到data数组中
list.toArray(data);
System.out.println("========");
System.out.println(Arrays.toString(data)); //[world, When?, What?, What?, GOOD]
// 数组长度小于list集合中元素的数量
String[] strings = new String[3];
String[] array = list.toArray(strings);
System.out.println(Arrays.toString(strings)); //[null, null, null]
System.out.println(Arrays.toString(array)); //[world, When?, What?, What?, GOOD]
// java.util.Arrays类提供一个方法 static <T> List<T> asList(T ...a) 可以把若干数据转换为List集合,形参是变长参数,实参可以传递保存数据的数组
// 把数组转换为List集合
// 注意:仅仅是提供了一种通过List集合操作数组元素的方式
List<String> asList = Arrays.asList(data);
System.out.println(asList); //[world, When?, What?, What?, GOOD]
// 修改数组元素
data[0] = "boy";
System.out.println(asList); //[boy, When?, What?, What?, GOOD]
// 修改asList集合中的元素
asList.set(1, "DTF");
System.out.println(Arrays.toString(data)); //[boy, DTF, What?, What?, GOOD]
// 注意:这个asList集合不支持 添加/删除 操作
// asList.add("oop"); //java.lang.UnsupportedOperationException
LinkedList集合
双向链表,集合中每个结点都包含着[上一个节点地址,数据,下一个节点地址]
LinkedList<String> list = new LinkedList<>();
// List所有的操作LinkedList都需要重写
// 所以,List所有的方法,LinkedList都有
list.add("add");
list.add("adds");
list.add("addsS");
list.add("addsX");
System.out.println(list); //[add, adds, addsS, addsX]
System.out.println(list.contains("add")); //true
System.out.println(list.size()); //4
list.remove("add");
System.out.println(list); //[adds, addsS, addsX]
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String next = iterator.next();
if (next.length() > 4) {
iterator.remove();
}
}
System.out.println(list); //[adds]
list.add(0, "Hello");
list.add(0, "Hi");
list.add(0, "Guys");
for (String s : list) {
System.out.print(s + " "); //Guys Hi Hello adds
}
System.out.println();
list.clear();
// LinkedList有一组模拟队列的方法,队列特点:先进先出
list.offer("1"); //入队,元素在链表尾部
list.offer("2");
list.offer("3");
System.out.println(list); //[1, 2, 3]
String poll = list.poll(); //出队,链表第一个元素返回并删除
System.out.println(poll); //1
System.out.println(list); //[2, 3]
String peek = list.peek(); //返回第一个元素,不删除
System.out.println(peek); //2
System.out.println(list); //[2, 3]
list.clear();
// 有一组模拟栈的操作,特点是后进先出
list.push("11"); //入栈,元素添加到链表头部
list.push("22");
list.push("33");
System.out.println(list); //[33, 22, 11]
String pop = list.pop(); //出栈,链表头部元素删除并返回
System.out.println(pop); //33
System.out.println(list); //[22, 11]
// 还有一组真对 第一个firse/最后一个last 元素的操作
list.addFirst("first"); //添加链表头部
System.out.println(list); //[first, 22, 11]
list.removeFirst();
System.out.println(list); //[22, 11]
list.addLast("Last");
System.out.println(list); //[22, 11, Last]
list.removeLast();
System.out.println(list); //[22, 11]
System.out.println(list.getFirst()); //22
System.out.println(list.getLast()); //11
list.offerFirst("top");
list.offerLast("bottom");
System.out.println(list); //[top, 22, 11, bottom]
System.out.println(list.peekFirst()); //top
System.out.println(list.peekLast()); //bottom
list.clear();
System.out.println(list); //[]
System.out.println(list.peekFirst()); //null
System.out.println(list.peekLast()); //null
// list.removeFirst(); //java.util.NoSuchElementException
// System.out.println(list.getFirst()); //java.util.NoSuchElementException
Set集合
Set<Integer> set = new HashSet<>();
// Set存储顺序与添加顺序可能不一样,且不允许存储重复数据
set.add(12794);
set.add(1341235);
set.add(14);
set.add(1);
System.out.println(set); //[1, 1341235, 12794, 14]
for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext(); ) {
Integer next = iterator.next();
System.out.println(next.hashCode());
}
set.clear();
Random random = new Random();
while (set.size() < 20) {
set.add(random.nextInt(100));
}
System.out.println(set); //[33, 2, 10, 42, 75, 44, 46, 48, 16, 81, 49, 18, 20, 52, 54, 86, 22, 23, 26, 30]
System.out.println(set.contains(28)); //true or false
for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext(); ) {
Integer next = iterator.next();
if (next > 60) {
iterator.remove();
}
}
System.out.println(set); //[33, 2, 10, 42, 44, 46, 48, 16, 49, 18, 20, 52, 54, 22, 23, 26, 30]
HashSet
HashSet<Person> hashSet = new HashSet<>();
hashSet.add(new Person("name", 36));
hashSet.add(new Person("name", 36));
hashSet.add(new Person("name", 36));
hashSet.add(new Person("name", 36));
hashSet.add(new Person("name", 36));
// 向HashSet集合中add()添加元素时,先根据元素的哈希码计算存储位置,因为在Person类中重写了equals()/hashCode(),所以上面添加所有的对象的哈希码都相等,计算出来的存储位置也一样
// 在进行equals比较时也相等,所以只添加了第一个对象,后面的对象都添加失败
System.out.println(hashSet.size()); //1
Person p = new Person("name", 36);
// contains() 先根据p对象的哈希码计算存储位置i,来到i位置查看存在equals相等的元素,返回true
System.out.println(hashSet.contains(p)); //true
TreeSet
TreeSet集合可以对元素进行排序
// 调用TreeSet(Comparator)构造方法,通过参数指定一个Comparator比较器
// 创建TreeSet集合存储字符串,通过参数指定Comparator比较器,根据字符串降序排序
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
treeSet.add("g");
treeSet.add("d");
treeSet.add("a");
treeSet.add("v");
treeSet.add("x");
treeSet.add("z");
System.out.println(treeSet); //[z, x, v, g, d, a]
/*
* 创建TreeSet集合时灭有在构造器方法指定Comparator比较器,要求元素本身具有比较大小的能力,即元素的类要实现Comparable接口
* String实现了Comparable接口,重写了compareTo()抽象方法,String字符串具有了比较大小的功能
* str1.compareTo(str2)两个字符串比较时,前面一个字符串大返回正数,对应升序
*/
TreeSet<String> treeSet2 = new TreeSet<>();
//把treeSet参数集合中的所有元素都添加到当前treeSet2集合中
treeSet2.addAll(treeSet);
System.out.println(treeSet2); //[a, d, g, v, x, z]
自定义类实现TreeSet排序
// 定义TreeSet存储Student对象,在构造方法中指定Comparator比较器,根据成绩降序排序
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.score - o1.score;
}
});
treeSet.add(new Student("aa", 30));
treeSet.add(new Student("bb", 32));
treeSet.add(new Student("Cc", 56));
treeSet.add(new Student("Dd", 99));
treeSet.add(new Student("ss", 103));
// 当前TreeSet根据学生的成绩进行排序,如果两个学生成绩相等则comparator比较器返回0,就认为是相同的元素
// Set集合不允许存储重复的数据
boolean result = treeSet.add(new Student("xi", 30));
System.out.println(result); //false,添加失败
for (Student student : treeSet) {
System.out.println(student);
/*
* Student{name='ss', score=103}
* Student{name='Dd', score=99}
* Student{name='Cc', score=56}
* Student{name='bb', score=32}
* Student{name='aa', score=30}
*/
}
Student stu = new Student("XXX", 99);
System.out.println(treeSet.contains(stu)); //true,当前TreeSet集合中存在成绩为70分的同学
// TreeSet可以对集合中的元素进行排序,如果没有在构造方法指定Comparator比较器,要求元素本身具有比较大小的功能,即元素的类要实现Comparable接口
TreeSet<Student> treeSet1 = new TreeSet<>();
// 把treeSet集合中所有的元素都添加到treeSet1集合中
treeSet1.addAll(treeSet);
System.out.println("--------------------------");
for (Student student : treeSet1) {
System.out.println(student);
/*
* Student{name='Cc', score=56}
* Student{name='Dd', score=99}
* Student{name='aa', score=30}
* Student{name='bb', score=32}
* Student{name='ss', score=103}
*/
}
Student类
static class Student implements Comparable<Student> {
String name;
Integer score;
public Student() {
}
public Student(String name, Integer score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) {
// 按照学生名排序
return this.name.compareTo(o.name);
}
}