Collection集合

集合的概念:
对象的容器,实现了对对象常用的操作
集合和数组的区别:
- 数组长度固定,集合长度不固定
- 数组可以存储基本类型和引用类型,集合只能存储引用类型
集合的添加删除等操作:
接口 Collection List Set 不能被实例化,其子类的实现类可以被实例化
package file.homework;
import java.util.ArrayList;
import java.util.Collection;
@SuppressWarnings({"all"})
public class HomeWork03 {
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add("jack");//添加
collection.add("mark");
collection.remove("jack");//删除
collection.size();//个数
System.out.println(collection.contains("jack"));//元素是否存在 true
System.out.println(collection.isEmpty());//集合是否为空 false
}
}
集合的遍历:
增强for循环:快捷键 I
for (Object o :collection) {
System.out.println(o);
}
迭代器(iterator):快捷键itit
Iterator iterator = collection.iterator();//collection集合对象
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println(obj);
}
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
String str = (String)iterator.next();//强转String
System.out.println(str);
}
迭代器迭代过程中的删除不能用集合的删除方法,会抛出异常,需用本身的删除方法
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
String str = (String)iterator.next();
iterator.remove();//删除元素
}
综合运用
集合中添加的是对象的地址,即使删除对象也是删除在集合里面的地址。堆中仍保留该new出来的对象
package com.Colle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Colle {
@SuppressWarnings({"all"})
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(new books("三国演义","罗贯中",10.1));
col.add(new books("小李飞刀","古龙",5));
col.add(new books("红楼梦","曹雪芹",18.1));
//得到col的迭代器
Iterator iterator = col.iterator();
//用while循环来遍历
while (iterator.hasNext()) {//判断是否有数据
//返回下一个元素,类型是Object
Object obj = iterator.next();
//books book = (books)iterator.next(); 也可以
System.out.println("obj="+ obj);
}
}
}
class books{
private String name;
private String author;
private double price;
public books(String name, String author, double price) {
this.name = name;
this.author = author;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "books{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
}
List
常用方法(列表迭代器)
使用列表迭代器

List实现类
- ArrayList 【重点】
- 数组结构实现,必须要连续空间,查询快、增删慢
- jdk1.2版本,运行效率块、线程不安全
- Vector
- 数组结构实现,查询快、增删慢
- jdk1.0版本,运行
- LinkedList
- 双向链表结构实现,无需连续空间,增删快,查询慢
ArrayList
遍历元素
列表迭代器
ListIterator li = arrayList.listIterator();
while(li.hasNext()){
Student s = (Student)li.next(); //从前往后遍历
}
while(li.hasPrevious()){
Student s = (Student)li.previous();//从后往前遍历
}
源码分析
DEFAULT_CAPACITY = 10; //默认容量
//注意:如果没有向集合中添加任何元素时,容量0,添加一个后,容量为10
//每次扩容是原来的1.5倍
Vector
public static void main(String[] args) {
Vector vector = new Vector();
vector.add("jack");
vector.add("mARK");
vector.add("tom");
Enumeration en = vector.elements();//使用枚举遍历
while (en.hasMoreElements()) {
Object obj = en.nextElement();
System.out.println(obj);
}
}
LinkedList(双向链表)
列表迭代器(同list一样)
ListIterator li = linkedlist.listIterator();
while(li.hasNext()){
System.out.println(li.nextIndex() + ":" + li.next()); //从前往后遍历
}
while(li.hasPrevious()){
System.out.println(li.previousIndex() + ":" + li.previous()); //从后往前遍历
}
LinkedList和ArrayList区别
ArrayList是数组 而 LinkedList是双向链表

泛型
- 本质是参数化类型,把类型作为参数传递
- 常见形式有泛型类、泛型接口、泛型方法
- 语法 T成为类型占位符,表示一种引用类型,可以写多个逗号隔开
- 好处 1. 提高代码重用性 2. 防止类型转换异常,提高代码安全性
- 泛型可以用于引用类型和基本数据类型的包装类(泛型不能直接使用基本数据类型)
定义一个泛型类
public class MyGeneric<T>{// 写一个泛型类
//使用泛型T
//1 创建变量
T t;
public void show(T t){//2 泛型作为方法的参数
System.out.println(t);
}
public T getT(){//3 泛型作为方法的返回值
return t;
}
}
使用泛型注意:
1. 泛型只能使用引用类型
2. 不同泛型类型对象之间不能相互赋值
3.使用数组的泛型不允许初始化,静态方法或属性不能使用泛型
(静态和类相关,类的加载在创建对象之前,泛型是在对象的创建所发生的)
public class TestGeneric{
public static void main(String[] args){
//使用泛型类创建对象
MyGeneric<String> myGeneric = new MyGeneric<String>();
myGeneric.t = "hello";
myGeneric.show("hello world!");
String string = myGeneric.getT();
MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>();
myGeneric2.t = 100;
myGeneric2.show(200);
Integer integer = myGeneric2.getT();
}
}
泛型接口
泛型接口的类型,在继承接口或者实现接口时确定
package com.customgeneric;
public class CustomInterfaceGeneric {
public static void main(String[] args) {
}
}
/*
* 泛型接口使用说明:
* 接口中,静态成员不能使用泛型
* 泛型接口的类型,在继承接口或者实现接口时确定
*
* */
//在继承接口 指定泛型接口的类型
interface IA extends IUsb<String ,Double>{}
//IA接口继承了接口IUsb(则指定了U为String类型,R为Double类型),故class AA 要实现IUsb接口中的所有方法
class AA implements IA{
@Override
public Double get(String s) {
return null;
}
@Override
public void hi(Double aDouble) {}
@Override
public void run(Double r1, Double r2, String u1, String u2) {}
@Override
public Double method(String s) {
return IA.super.method(s);
}
}
//实现接口时,直接指定泛型接口的类型
class BB implements IUsb<Integer,Float>{
@Override
public Float get(Integer integer) {
return null;
}
@Override
public void hi(Float aFloat) {}
@Override
public void run(Float r1, Float r2, Integer u1, Integer u2) {}
}
//没有指定类型,默认为Object
//即使不指定,最好写成 class CC implementsIUsb<Object,Object>{...}
class CC implements IUsb{
@Override
public Object get(Object o) {
return null;
}
@Override
public void hi(Object o) {}
@Override
public void run(Object r1, Object r2, Object u1, Object u2) { }
}
interface IUsb<U,R>{
//U name; 不能这样使用
//普通方法中,可以使用泛型接口
R get(U u);
void hi(R r);
void run(R r1,R r2,U u1,U u2);
//在JDK8中,可以在接口中使用默认方法,也可以使用泛型
default R method(U u){
return null;
}
}
泛型方法
语法格式:在方法的返回值类型(void/String/int)前面写<T>
调用泛型方法时,不需要填写泛型类型,只填写参数即可,编译器自己会确定类型
package com.customgeneric;
import java.util.ArrayList;
public class CustomMethodGeneric {
public static void main(String[] args) {
Car car = new Car();
car.fly("宝马",100);//当调用方法时,传入参数,编译器就会确定类型
car.fly(300,100.678);
Fish<String, ArrayList> fish = new Fish<>(); //T--> String R-->ArrayList
fish.hello(new ArrayList(),11.3f);
}
}
//泛型方法可以定义在普通类,也可定义在泛型类中
class Car{
public void run(){}//普通方法
public <T,R> void fly(T t,R r){
System.out.println(t.getClass());//String
System.out.println(r.getClass());//Integer 主方法中的100会自动装箱,封装成Integer
}//泛型方法
}
//泛型类
class Fish<T,R>{
public void run(){}//普通方法
public <U,I> void eat(U u,I i){}//泛型方法
//非泛型方法,而是方法使用了泛型
public void hi(T t){}
//泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型
public <K> void hello(R r,K k){//T使用了类声明的,K 是用了自己声明的
System.out.println(r.getClass());//ArrayList
System.out.println(k.getClass());//Float
}
}
泛型好处
1.提高代码重用性
2.防止类型转换异常,提高代码安全性
泛型集合
概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
特点:
- 编译时即可检查,而非运行时抛出异常
- 访问时,不必类型转换(拆箱)
- 不同泛型之间应用不能相互赋值,泛型不存在多态
Student类
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
泛型集合
public static void main(String[] args) {
ArrayList<String> ar = new ArrayList<>();
ar.add("jack");
ar.add("Tom");
// ar.add(100);报错,类型不匹配。只能是String
Iterator<String> stringIterator = ar.iterator();
while (stringIterator.hasNext()) {
String next = stringIterator.next();
System.out.println(next);
}
ArrayList<Student> ar1 = new ArrayList<>();
ar1.add(new Student("Jery",13));
ar1.add(new Student("Amy",17));
for (Object o :ar1) {
System.out.println(o);
}
}

Set
HashSet
基于hashMap实现
存储结构:哈希表(数组+链表+红黑树) 红黑树是JDK1.8之后加的
输出顺序无序,但每次的输出的顺序一致,只是与输入顺序有可能不一致
存储过程(重复依据)
- 根据hashCode计算保存的位置,如果位置为空,直接保存,若不为空,进行第二步
- 再执行equals方法,如果equals为true,则认为是重复,否则形成链表
特点
- 基于HashCode计算元素存放位置
- 利用31这个质数,减少散列冲突
- 31提高执行效率
31 * i = (i << 5) - i转为移位操作
- 31提高执行效率
- 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入
- 利用31这个质数,减少散列冲突
新建集合 HashSet<String> hashSet = new HashSet<>();
添加元素 hashSet.add( );
删除元素 hashSet.remove( );
遍历操作
1. 增强for for( type type : hashSet)
2. 迭代器 Iterator<String> it = hashSet.iterator( );
判断 hashSet.contains( ); hashSet.isEmpty();
TreeSet
特点
- 基于排列顺序实现元素不重复
- 实现SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable接口,指定排序规则
- 通过CompareTo方法确定是否为重复元素
存储结构:红黑树()
红黑树是一种自平衡的二叉搜索树,它在插入和删除操作后会通过一系列的旋转和重新着色操作来保
持树的平衡。红黑树的每个节点都有一个额外的表示节点颜色的属性,可以是红色或黑色。
红黑树具有以下特性:
每个节点要么是红色,要么是黑色。
根节点是黑色。
所有叶子节点(NIL节点)都是黑色。
如果一个节点是红色的,则其两个子节点都是黑色的。
从任意节点到其每个叶子节点的路径上包含相同数量的黑色节点。
创建集合 TreeSet<String> treeSet = new TreeSet<>()
添加元素 treeSet.add();
删除元素 treeSet.remove();
遍历 1. 增强for 2. 迭代器
判断 treeSet.contains();
补充:TreeSet集合的使用
Comparator 实现定制比较(比较器)
Comparable 可比较的
// 重写compare
@override
public int compare(Person o1, Person o2){
int n1 = o1.getAge()-o2.getAge();
int n2 = o1.getName().comareTo(o2.getName());
return n1 == 0 ? n2 : n1;
}
代码实现
Person类
在实现Comparable接口时,使用泛型可以指定比较的对象类型。这样在使用compareTo()方法时, 编译器会检查传入的参数类型是否与泛型类型一致,从而避免了类型不匹配的错误
实现Comparable接口就要实现其compareTo方法
package file.homework;
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/*
* 使用int类型来接受比较的结果是因为compareTo()方法需要返回一个整数值来
* 表示两个对象的比较结果。根据约定,如果两个对象相等,则返回0;如果当前对象
* 小于参数对象,则返回负数;如果当前对象大于参数对象,则返回正数
* */
@Override
public int compareTo(Person o) {
int n1 = this.name.compareTo(o.getName());
int n2 = this.age-o.getAge();
return n1==0?n2:n1;
}
}
main方法
package file.homework;
import java.util.Iterator;
import java.util.TreeSet;
@SuppressWarnings({"all"})
public class HomeWork03 {
public static void main(String[] args) {
TreeSet<Person> people = new TreeSet<>();
people.add(new Person("jack",23));
people.add(new Person("amy",22));
people.add(new Person("tom",29));
people.add(new Person("小名",22));
people.add(new Person("丁凯",23));
people.add(new Person("雄安红",29));
people.add(new Person("雄安红",29));
//System.out.println(people.size()+people.toString());
Iterator<Person> iterator = people.iterator();
while (iterator.hasNext()) {
Person next = iterator.next();
System.out.println(next);
}
}
}

代码实现(Comparator比较器)
值得注意的是:在比较器或者是实现Comparable接口中。根据先比较年龄还是姓名决定输出的排序结果。如果实现了Comparator比较器就无需再次实现Comparable接口了。
package file.homework;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
@SuppressWarnings({"all"})
public class HomeWork03 {
public static void main(String[] args) {
TreeSet<Person> people = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1 = o1.getAge() - o2.getAge();
int n2 = o1.getName().compareTo(o2.getName());
return n2==0?n1:n2;
}
});
people.add(new Person("jack",23));
people.add(new Person("amy",22));
people.add(new Person("tom",29));
// people.add(new Person("tom",29));
people.add(new Person("小名",22));
people.add(new Person("丁凯",23));
people.add(new Person("雄安红",29));
people.add(new Person("雄安红",29));
// System.out.println(people.size()+people.toString());
Iterator<Person> iterator = people.iterator();
while (iterator.hasNext()) {
Person next = iterator.next();
System.out.println(next);
}
}
}
Map集合

hashMap、treeMap 都用keySet、entrySet遍历
特点
1. 用于存储任意键值对(key - value)
2. 键:无序、无下标、不允许重复(唯一) key的值可以为null
3. 值:无序、无下标、允许重复
HashMap
存储结构:哈希表(数组+链表+红黑树)
使用key可使hashcode和equals作为重复
增、删、遍历、判断与上述一致
原码分析总结:
- HashMap刚创建时,table是null,节省空间,当添加第一个元素时,table容量调整为16
- 当元素个数大于阈值(16*0.75 = 12)时,会进行扩容,扩容后的大小为原来的两倍,目的是减少调整元素的个数
- jdk1.8 当每个链表长度 >8 ,并且数组元素个数 ≥64时,会调整成红黑树,目的是提高效率
- jdk1.8 当链表长度 <6 时 红黑树调整成链表
- jdk1.8 以前,链表时头插入,之后为尾插入
代码实现
keySet的返回值是Set集合,里面存放的所有的key
entrySet的返回值也是Set集合,把里面的每一个Key,Value封装成一个个Entry
entrySet效率高于keySet
package file.homework;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"all"})
public class HomeWork03 {
public static void main(String[] args) {
HashMap<Integer, String> hashMap = new HashMap<>();
hashMap.put(1,"jack");
hashMap.put(1,"amy");
hashMap.put(null,"tom");
hashMap.put(3,"jery");
//使用keySet
Set<Integer> keys = hashMap.keySet();
for (Integer o :keys) {
System.out.println(o+":"+hashMap.get(o));
}
//使用entrySet
Set<Map.Entry<Integer, String>> entries = hashMap.entrySet();
for (Map.Entry<Integer, String> o :entries) {
System.out.println(o);
}
}
}
package file.homework;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"all"})
public class HomeWork03 {
public static void main(String[] args) {
HashMap<Person, String> hashMap = new HashMap<>();
hashMap.put(new Person(null,0),"山东");
hashMap.put(new Person("amy",13),"北京");
hashMap.put(new Person("jery",34),"上海");
hashMap.put(new Person("tom",23),"天津");
//使用keySet
Set<Person> people = hashMap.keySet();
for (Person o :people) {
System.out.println(o + hashMap.get(o));
}
System.out.println("======");
//使用entrySet
Set<Map.Entry<Person, String>> entries = hashMap.entrySet();
for (Map.Entry<Person, String> personStringEntry :entries) {
System.out.println(personStringEntry);
}
}
}
TreeMap
实现了SortedMap接口(是map的子接口),可以对key自动排序
遍历方式:keySet entrySet
implements Comparable方法
package file.homework;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@SuppressWarnings({"all"})
public class HomeWork03 {
public static void main(String[] args) {
TreeMap<Person, String> treeMap = new TreeMap<>();
treeMap.put(new Person("amy",13),"北京");
treeMap.put(new Person("jery",34),"上海");
treeMap.put(new Person("tom",23),"天津");
//使用keySet
Set<Person> people = treeMap.keySet();
for (Person o :people) {
System.out.println(o + treeMap.get(o));
}
System.out.println("======");
//使用entrySet
Set<Map.Entry<Person, String>> entries = treeMap.entrySet();
for (Map.Entry<Person, String> personStringEntry :entries) {
System.out.println(personStringEntry);
}
}
}
Comparator(比较器)
package file.homework;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@SuppressWarnings({"all"})
public class HomeWork03 {
public static void main(String[] args) {
TreeMap<Person, String> treeMap = new TreeMap<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int n1= o1.getName().compareTo(o2.getName());
int n2 = o1.getAge() - o2.getAge();
return n1==0?n2:n1;
}
});
treeMap.put(new Person("amy",13),"北京");
treeMap.put(new Person("jery",34),"上海");
treeMap.put(new Person("tom",23),"天津");
//使用keySet
Set<Person> people = treeMap.keySet();
for (Person o :people) {
System.out.println(o + treeMap.get(o));
}
System.out.println("======");
//使用entrySet
Set<Map.Entry<Person, String>> entries = treeMap.entrySet();
for (Map.Entry<Person, String> personStringEntry :entries) {
System.out.println(personStringEntry);
}
}
}
Collections工具类
13.42 Collections工具类_哔哩哔哩_bilibili
list转数组,数组的长度若定义的比列表的短,则转成数组后列表长度和数组长度相等。如是定义的长度大于列表的长度,则转成数组后多余的为null
// list转成数组
Integer[] arr = list.toArray(new Integer[10]);
sout(arr.length);
sout(Array.toString(arr));
// 数组转成集合
// 此时为受限集合,不能 添加和删除!
String[] names = {"张三","李四","王五"};
List<String> list2 = Arrays.asList(names);
// 把基本类型数组转为集合时,需要修改为包装类
Integer[] nums = {100, 200, 300, 400, 500};
List<Integer> list3 = Arrays.asList(nums);
总结

本文详细介绍了Java集合框架中的ArrayList、LinkedList、HashSet和TreeSet的特性和使用,包括添加、删除、遍历等操作,以及泛型在集合中的应用,强调了泛型的安全性和重用性。同时,讲解了Map接口的实现类HashMap和TreeMap,以及如何通过Comparator或Comparable实现自定义排序。
4246

被折叠的 条评论
为什么被折叠?



