JAVA 集合

1. 集合

  • 集合的定义:对象的容器,定义了多个对象进行操作的常用方法。
  • 和数组区别:
  1. 数组长度固定,集合长度不固定。
  2. 数组可以存储基本类型和引用类型,集合只能存储引用类型。
  • 位置:java.util.*;

2. Collection体系

在这里插入图片描述

2.1 Collection父接口

特点:代表一组任意类型的对象,无序,无下标,不能重复
创建集合java Collection collection = new ArrayList();

  • 常用方法
  1. 添加元素 collection.add();
  2. 删除元素
    collection.remove();
    collection.clear();
  3. 遍历元素(重点)
    1. 使用增强for(无下标)
      for(Object object : collection){}
    2. 使用迭代器
hasNext(); 有没有下一个元素
next(); 获取下一个元素
remove(); 删除当前元素
Interator it = collection.iterator();
while(it.hasNext()) {
    String object = (String)it.next();//强转
	//可以使用it.remove(); 进行删除元素
	// collection.remove(); 不能使用collection其他方法 会报并发修改异常
}
  1. 判断
    collection.contains();
    collection.isEmpty();

2.2 List子接口

特点:有序,有下标,元素可重复
创建集合对象 List list = new ArrayList<>();

  • 常用方法
  1. 添加元素list.add();会对基本类型进行自动装箱
  2. 删除元素 可以用索引 list.remove(0);
    当删除数字与索引矛盾时 对数字强转list.remove((Object) 10)list.remove(new Integer(10))
  3. 遍历
package collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/**
 * List子接口的使用
 * 特点:1.有序有下标 2.可以重复
 * @author zzz
 */

public class demo03 {
    public static void main(String[] args) {
        //先创建集合对象
        List list = new ArrayList<>();
        //1.添加元素
        list.add("苹果");
        list.add("小米");
        list.add(0, "华为");
        System.out.println(list.size());
        System.out.println(list.toString());
        //2.删除元素
        //list.remove("苹果");
        //System.out.println(list.size());
        //System.out.println(list.toString());
        //3.遍历
        //3.1使用for遍历
        System.out.println("=====3.1使用for遍历=====");
        for(int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //3.2使用增强for遍历
        System.out.println("=====3.2使用增强for遍历=====");
        for(Object object : list) {
            System.out.println(object);
        }
        //3.3使用迭代器
        System.out.println("=====3.3使用迭代器=====");
        Iterator it = list.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
        //3.4使用列表迭代器,和Iterator的区别,ListIterator可以向前或前后遍历,添加,删除,修改元素
        ListIterator lit = list.listIterator();
        System.out.println("=====3.4使用列表迭代器从前往后=====");
        while(lit.hasNext()) {
            System.out.println(lit.nextIndex() + ":" + lit.next());
        }
        System.out.println("=====3.4使用列表迭代器从后往前=====");
        while(lit.hasPrevious()) {
            System.out.println(lit.previousIndex() + ":" + lit.previous());
        }

        //4.判断
        System.out.println(list.contains("苹果"));
        System.out.println(list.isEmpty());

        //5.获取位置
        System.out.println(list.indexOf("华为"));

        
    }
}

补充:List subList = list.subList(1, 3);(区间左闭右开,索引:1~2)

2.3 List实现类

  • ArrayList【重点】
    数组结构实现,必须要连续空间,查询快,增删慢。
    jdk1.2版本,运行效率快,线程不安全。
  • Vector
    数组结构实现,查询快,增删慢。
    jdk1.0,运行效率低,线程安全。
  • LinkedList
    双向链表结构实现,无需连续空间,增删快,查询慢。
    运行效率快,线程不安全。

ArrayList
创建集合:ArrayList arraylist = new ArrayList<>();

  1. 添加元素:arraylist.add();
  2. 删除元素:arraylist.remove(new Student("name", 10));
    这里重写了equals(this == obj)
public boolean equals(Object obj){
    //1 判断是不是同一个对象
    if(this == obj){
    return true;
}
	//2 判断是否为空
if(obj == null){
    return false;
}
	//3 判断是否是Student类型
if(obj instanceof Student){
    Student == (Student)obj;
    //4 比较属性
    if(this.name.equals(s.getName()) && this.age == s.getAge()){
        return true;
    }
}
	//5 不满足条件返回false
    return false;
}
  1. 遍历元素【重点】

使用迭代器

Iterator it = arrayList.iterator();
while(it.hasNext()){
    Student s = (Student)it.next(); //强转
}

列表迭代器

ListIterator li = arrayList.listIterator();
while(li.hasNext()){
    Student s = (Student)li.next(); //从前往后遍历
}

while(li.hasPrevious()){
    Student s = (Student)li.previous();//从后往前遍历
}
  1. 源码分析
DEFAULT_CAPACITY = 10; //默认容量
//注意:如果没有向集合中添加任何元素时,容量0,添加一个后,容量为10
//每次扩容是原来的1.5倍
elementData存放元素的数组
size 实际元素个数

底层源码

public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}
public void ensureCapacity(int minCapacity) {
    if (minCapacity > elementData.length
        && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
             && minCapacity <= DEFAULT_CAPACITY)) {
        modCount++;
        grow(minCapacity);
    }
}
private Object[] grow(int minCapacity) {
    int oldCapacity = elementData.length;
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, /* minimum growth */
                oldCapacity >> 1           /* preferred growth */);
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else {
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
    }
}

Vector
创建集合Vector vector = new Vector<>();
增加,删除,判断同上
遍历中枚举器遍历

Emumeration en = vector.elements();
while(en.hasMoreElements()) {
    String s = (String)en.nextElement();
    System.out.println(s);
}

LinkedList
创建链表集合:Linkedlist list = new LinkedList<>();
常用方法和List一致

2.4 泛型

  • 本质是参数化类型,把类型作为参数传递
  • 常见形式有泛型类、泛型接口、泛型方法
  • 语法 T 成为类型占位符,表示一种引用类型,可以写多个逗号隔开
  • 好处 1. 提高代码重用性 2. 防止类型转换异常,提高代码安全性

泛型类

//写一个泛型类
public class MyGeneric<T> {
    //使用泛型T
	//1.创建变量
	T t;
    //2.泛型作为方法的参数
	public void show(T t) {
        System.out.println(t);
    }
    //3.泛型作为方法的返回值
    public T getT() {
        return t;
    }
}
package genericity;

public class TestGeneric {
    public static void main(String[] args) {
        //使用泛型创建对象
        //注意:1.泛型只能使用引用类型 2.不同泛型对象不能相互复制
        MyGeneric<String> myGeneric = new MyGeneric<String>();
        myGeneric.t = "hello";
        myGeneric.show("world");
        String string = myGeneric.getT();

        MyGeneric<Integer> myGeneric2 = new MyGeneric<Integer>();
        myGeneric2.t = 100;
        myGeneric2.show(200);
        Integer integer = myGeneric2.getT();
    }
}

泛型接口

语法:接口名
注意:不能泛型静态常量

public class MyInterfaceImpl2<T> implements MyInterface<T>{
    
    @Override
    public T server(T t) {
        System.out.println(t);
        return null;
    }
}

泛型方法

语法:返回值类型

public class MyGenericMethod {
    //泛型方法
    public <T> T show(T t) {
        System.out.println("泛型方法:" + t);
        return t;
    }
}

//调用
MyGenericMethod myGenericMethod = new MyGenericMethod();
myGenericMethod.show("中国加油");
myGenericMethod.show(200);
myGenericMethod.show(3.14);

泛型集合

概念:参数化类型,类型安全的集合,强制集合元素的类型必须一致
特点:

  1. 编译时即可检查,而非运行时抛出异常
  2. 访问时,不必类型转换(拆箱)
  3. 不同泛型之间应用不能相互赋值,泛型不存在多态
public class demo07 {
    public static void main(String[] args) {
        ArrayList<String> arraylist1 = new ArrayList<String>();
        arraylist1.add("aaple");
        arraylist1.add("melon");
        arraylist1.add("mango");

        ArrayList<Student> arrayList2 = new ArrayList<Student>();
        Student s1 = new Student("张三", 18);
        Student s2 = new Student("老王", 20);
        Student s3 = new Student("王二", 22);
        arrayList2.add(s1);
        arrayList2.add(s2);
        arrayList2.add(s3);

        Iterator<Student> it = arrayList2.iterator();
        while(it.hasNext()) {
            Student s = it.next();
            System.out.println(s.toString());
        }
    }
}

2.5 Set集合

特点:无序,无下标,元素不可重复
方法:全部继承自Collection中的方法
增删遍历判断与collection一致

HashSet【重点】

存储结构:哈希表(数组+链表+jdk1.8红黑树)
存储过程(重复依据)

  1. 根据hashCode计算保存的位置,如果位置为空,直接保存,若不为空,则进行第二步。
  2. 再执行equals方法,如果equals为true,则认为是重复,拒绝插入,否则形成链表。

特点:

  1. 基于HashCode计算元素存放位置
  • 利用31这个质数,减少散列冲突
  • 31提高执行效率 31 * i = (i << 5) - i 转为移位操作
  • 当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入

新建集合HashSet<String>hashSet = new HashSet<String>();
添加元素hashSet.add();
删除元素hashSet.remove();
遍历操作

  1. 增强for for(type type: hashSet)
  2. 迭代器Iterator<String> it = hashSet.iterator();
    判断hashSet.contains(); hashSet.isEmpty();

TreeSet

特点

  • 基于排列顺序实现元素不重复
  • 实现SortedSet接口,对集合元素自动排序
  • 元素对象的类型必须实现Comparable接口,指定排序规则
  • 通过Compare To方法确定是否为重复元素
    存储结构:红黑树

创建集合TreeSet<String> treeSet = new TreeSet<>();
添加元素treeSet.add();
删除元素treeSet.remove();
遍历:1.增强for 2.迭代器
判断treeSet.contains(); treeSet.isEmpty();
补充: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;
}
TreeSet<Person> persons = 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 n1 == 0 ? n2 : n1;
    }
});
TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        int n1 = o1.length() - o2.length();
        int n2 = o1.compareTo(o2);
        return n1 == 0 ? n2 : n1;
    }
});

Map
Map接口的特点:

  1. 用于存储任意键值(key,value)
  2. 键:无序,无下标,不允许重复(唯一)
  3. 值:无序,无下标,允许重复
    方法:
  4. V put(K key, V value)将对象存到集合中,关联键值
  5. Object get(Object key)根据键获得对应的值
  6. Set 返回所有的Key
  7. Collection values() 返回包含所有的Collection集合
  8. Set<Map.Entry<K, V>> 键值匹配的Set集合
  9. Map.Entry映射对 entrySet效率高于keySet
    Map接口的使用:
//创建Map集合
Map<String, String> map = new HashMap<>();
// 1. 添加元素
map.put("cn", "中国");
map.put("uk", "英国");
map.put("cn", "zhongguo"); // 会替换第一个 
// 2. 删除
map.remove("uk");
// 3. 遍历
// 3.1 使用KeySet()
//Set<String> keyset = map.keySet(); // 所有Key的set集合
for(String key : map.keyset){
  sout(key + "---" + map.get(key));
}
// 3.2 使用entrySet()
//Set<Map.Entry<String, String>> entries = map.entrySet();
for(Map.Entry<String, String> entry : map.entries){
  sout(entry.getKey() + "---" + entry.getValue();
}
//4.判断
System.out.println(map.containsKey("a"));
System.out.println(map.containsValue("bc"));
System.out.println(map.isEmpty());

HashMap【重点】
存储结构:哈希表(数组+链表 +红黑树)
使用key可使hashcode和equals作为重复
增,删,遍历,判断与上述一致
源码分析和总结:

  1. HashMap刚创建的时候,table是null,节省空间,当添加第一个元素时,table容量调整为16
  2. 当元素个数大于阈值(16 * 0.75 = 12)时,会进行扩容,扩容后的大小为原来的两倍,目的是减少调整元素的个数
  3. jdk1.8当每个链表长度 > 8,并且数组元素个数 >= 64时,会调整成红黑树,目的是提高效率
  4. jdk1.8当链表程度 < 6时,调整成链表
  5. jdk1.8以前,链表时头插入,之后为尾插入
  • put方法源码分析:
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
  • Hashtable
    线程安全,运行效率慢;不允许null作为key或value
  • Properties
    hashtable的子类,要求key和value都是String,通常用于配置文件的读取
  • TreeMap实现了SortedMap接口(是map的子接口),可以对key自动排序

3. Collection工具类

概念:集合工具类,定义了除了存取以外的集合常用方法
直接二分查找int i = Collections.binarySearch(list, x);成功返回索引
其他方法:copy复制,reverse反转,shuffle打乱
补充:

// list转成数组
Integer[] arr = list.toArray(new Integer[10]);
sout(arr.length);
System.out.println(Array.toString(arr));

// 数组转成集合
// 此时为受限集合,不能 添加和删除!
String[] name = {"张三","李四","王五"};
List<String> list2 = Arrays.asList(names)	;

// 把基本类型数组转为集合时,需要修改为包装类
Integer[] nums = {100, 200, 300, 400, 500};
List<Integer> list3 = Arrays.asList(nums);
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值