集合的基础知识

集合(Collection篇)

一、泛型

1. 概念

泛型(Generics)是JDK1.5的一个新特性,其实就是一个【语法糖】,本质上就是编译器为了提供更好可读性而提供的一种小手段,小技巧,虚拟机层面是不存在所谓泛型概念的。

2. 作用

  • 通过泛型的语法定义,约束集合元素的类型,进行安全检查,把错误显示在编译期;
  • 代码通用性更强
  • 泛型可以提升程序代码的可读性,但它只是一个语法糖(编译后这样的东西就被删除,不出现在最终的源代码中),对于JVM运行时的性能是没有任何影响的。

3. 泛型声明(使用位置)

  • 泛型可以在接口、类、方法的返回值上使用

    java.util.List泛型接口/类

    public interface Collection<E> {}

  • 泛型方法的声明

    public <E> void print(E e){}

    在方法返回值前声明了一个<E>表示后面出现的E是泛型,而不是普通的Java变量。

4. 常用名称

  • E -Element(在集合中使用,因为集合中存放的是元素)
  • T -Type(Java类)
  • K -Key(键)
  • V -Value(值)
  • N -Number(数值类型)
  • ? -表示不确定的java类型

5. 用途

  1. 编译时类型检查
  2. 代码通用性更强
package cn.tonyoliver.generics;

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

/**
 * 这个类用来测试泛型用途一:编译时做类型检查
 * 
 * @author Tony
 *
 */
public class Test01_Generics {
    
    
	public static void main(String[] args) {
    
    
		int[] a = new int[3];
		a[0] = 1;
		a[1] = 2;
		// int类型的数组,规定了数组里的数据类型,类型不对就报错
//		a[2] = "hello";

		// 1,泛型的标志<>
		// 2,泛型的好处:规定了数据的类型,不能想放什么类型的数据就放什么类型的,要遵守泛型规定的类型
		// 3,泛型的数据类型只能是引用类型,不能是基本类型
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		// 4,如果类型不对,把运行期才会报的错ClassCastException直接在编译时期就报出来
//		list.add("a");//The method add(Integer) in the type List<Integer> is not applicable for the arguments (String)

//		Iterator it = list.iterator();
//		while(it.hasNext()) {
    
    
//			Integer s = (Integer)it.next();
//			System.out.println(s);
//		}
		Iterator<Integer> it = list.iterator();
		while (it.hasNext()) {
    
    
			Integer s = it.next();
			System.out.println(s);
		}
	}
}

package cn.tonyoliver.generics;

/**
 * 这个类用来测试泛型用途一:代码通用性更强
 * 
 * @author Tony
 *
 */
public class Test02_Generics {
    
    
	public static void main(String[] args) {
    
    
		// traditon();// 传统方法
		generics();// 泛型方法
	}

	// 传统方法:通过重载多态实现,方法同名,参数类型不同
	private static void traditon() {
    
    
		Integer[] scores = new Integer[] {
    
     100, 98, 80 };
		String[] names = new String[] {
    
     "语文", "数学", "英语" };

		Test02_Generics.print(scores);
		Test02_Generics.print(names);
	}

	private static void print(Integer[] ss) {
    
    
		for (Integer d : ss) {
    
    
			System.out.println(d);
		}
	}

	private static void print(String[] dd) {
    
    
		for (String s : dd) {
    
    
			System.out.println(s);
		}
	}

	// 泛型方法
	private static void generics() {
    
    
		Integer[] scores = new Integer[] {
    
     100, 98, 80 };
		String[] names = new String[] {
    
     "语文", "数学", "英语" };
		Double[] moneys = new Double[] {
    
     10.2, 20.2, 30.3 };

		Test02_Generics.print(scores);
		Test02_Generics.print(names);
		Test02_Generics.print(moneys);
	}

	public static <E> void print(E[] arr) {
    
    
		for (E e : arr) {
    
    
			System.out.println(e);
		}
	}

}

6. 类型擦除

泛型只是在编译期间生存,编译后就被干掉了,真正运行时,大多情况下而取而代之的是Object。

利用的是jdk提供的强大的反射功能。

package cn.tonyoliver.generics;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 这个类用来测试类型擦除
 * 
 * @author Tony
 *
 */
public class Test03_GenericsRemove {
    
    
	public static void main(String[] args) throws Exception {
    
    
		List<Integer> list = new ArrayList<Integer>();

		// 1,编译器按泛型检查,类型报错,这是在编译时期
//		list.add("chen");//The method add(Integer) in the type List<Integer> is not applicable for the arguments (String)

		// 2,但在实际运行时,泛型的地方就被替代为通用类型Object
		Class<?> clazz = list.getClass();
		Method m = clazz.getDeclaredMethod("add", Object.class);

		// 3,利用反射得到的对象是运行时对象,就可以设置非整型的数据
		m.invoke(list, "chen");

		System.out.println(list.get(0));
	}
}


二、集合

1. 概述

  1. 目前的程序中,我们可以把多个数据放入数组中存放,数组是作为多个数据存放的容器;
  2. 数组优缺点:要求数据类型是单一类型 + 数组一旦创建长度不可变 + 遍历方式单一 + 不适合插入删除
  3. 集合里有很多种工具类,都有很严格的继承结构,顶级父类是一个接口Collection接口

2. 集合的继承结构

上层的形成主要是提取了下层的共性形成了抽象层;

下层主要使用上层提供的各种方法进行使用。

在这里插入图片描述

三、Collection接口

1. Collection接口

Collection层次结构中的根接口。Collection表示一组对象,这些对象也称为Collection的元素。一些Collection允许有重复的元素,而另一些则不允许。一些Collection是有序的,而有些是无序的。

  • List接口:数据有序,可以重复
    • ArrayList子类
    • LinkedList子类
  • Set接口:数据无序,不可存重复值
    • HashSet
  • Map接口:键值对存数据
    • HashMap
  • Collections工具类

2. 常用方法

  • boolean add(E e):添加元素;
  • boolean addAll(Collection c):把小集合添加到大集合中;
  • boolean contains(Object o):如果此collection包含指定的元素,则返回true;
  • boolean isEmpty():如果此collection没有元素,则返回true;
  • Iterator<E> iterator():返回在此collection的元素上进行迭代的迭代器;
  • boolean remove(Object o):从此collection中移除指定元素的单个实例;
  • int size():返回collection中的元素数;
  • Object[] toArray():返回对象元素;
  • Object[] toArray() :返回包含此 collection 中所有元素的数组。
package cn.tonyoliver.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**
 * 这个类用来测试Collection接口
 * 
 * @author Tony
 *
 */
public class Test04_Collection {
    
    
	public static void main(String[] args) {
    
    
		// 1,创建对象
		// ArrayList is a raw type. References to generic type ArrayList<E> should be
		// parameterized
		// ArrayList是原始类型。对泛型类型ArrayList<E>的引用应参数化
		// Collection c = new ArrayList();
		Collection<String> c = new ArrayList<>();

		// 2,调用方法
		c.add("杨幂");
		c.add("赵丽颖");
		c.add("皮皮虾");
//		c.add(123);//添加元素的类型,没有通过泛型的类型检查,会直接报错

		System.out.println(c);
		// c.clear();
		System.out.println(c.contains("杨幂"));// true,判断集合中是否包含指定的元素
		System.out.println(c.equals("杨幂"));// false,判断集合是否和指定元素相等
		System.out.println(c.hashCode());// 获取集合在内存中的哈希码值
		System.out.println(c.isEmpty());// 判断集合是否为空
		System.out.println(c.size());// 获取集合中元素个数(集合的长度)
		System.out.println(c.remove("赵丽颖"));// 移除集合中的指定元素
		System.out.println("c" + c);

		Object[] objs = c.toArray();// 把集合转成数组
		System.out.println(Arrays.toString(objs));
		// 集合间的操作
		Collection<String> c2 = new ArrayList<>();
		c2.add("周杰伦");
		c2.add("杨幂");
		c2.add("赵丽颖");
		System.out.println(c.addAll(c2));// 向c集合中加入c2的数据
		System.out.println("c" + c);
		System.out.println(c.containsAll(c2));// 判断c中是否包含c2的所有元素
		// System.out.println(c.removeAll(c2));//获取c和c2的差集
		System.out.println("--c" + c);
		System.out.println(c.retainAll(c2));
		System.out.println("++c" + c);// 获取c和c2的交集

		// 集合的迭代
		// Iterator是一个接口,专门用来 迭代集合里的元素
		Iterator<String> it = c.iterator();
		while (it.hasNext()) {
    
    
			System.out.println(it.next() + "===");
		}
	}
}

四、List接口

是collection接口的子接口,继承了Collection接口的所有功能

1. 概念

有序的collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

2. 特点

  • 数据有序;
  • 允许存放重复元素;
  • 元素都有整数索引;
  • 可以存储多个null。

3. 常用方法

有继承自Collection接口的方法,也可以有特有的方法。

  • boolean add(E e):添加元素;
  • boolean addAll(Collection c):把小集合添加到大集合中;
  • boolean contains(Object o):如果此collection包含指定的元素,则返回true;
  • boolean isEmpty():如果此collection没有元素,则返回true;
  • Iterator<E> iterator():返回在此collection的元素上进行迭代的迭代器;
  • boolean remove(Object o):从此collection中移除指定元素的单个实例;
  • int size():返回collection中的元素数;
  • Object[] toArray():返回对象元素;
  • Object[] toArray() :返回包含此 collection 中所有元素的数组。

以下是List的特有方法

  • void add(int index, E element)
    在列表的指定位置插入指定元素(可选操作)。
  • boolean addAll(int index, Collection<? extends E> c)
    将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
  • E get(int index)
    返回列表中指定位置的元素。
  • int indexOf(Object o)
    返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
  • int lastIndexOf(Object o)
    返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
  • ListIterator listIterator()
    返回此列表元素的列表迭代器(按适当顺序)。
  • ListIterator listIterator(int index)
    返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
  • E remove(int index)
    移除列表中指定位置的元素(可选操作)。
  • E set(int index, E element)
    用指定元素替换列表中指定位置的元素(可选操作)。
  • List subList(int fromIndex, int toIndex)
    返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

ListIterator<E>接口是Iterator<E>的子接口,子接口丰富了遍历方式,除了可以顺序遍历,还可以逆向向前遍历。

List的遍历方法

  • Iterator遍历
  • ListIterator遍历
  • for循环遍历
  • for-each循环遍历

测试

package cn.tonyoliver.collection;

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

/**
 * 这个类用来测试List接口
 * 
 * @author Tony
 *
 */
public class Test05_List {
    
    
	public static void main(String[] args) {
    
    
		// 1,创建对象--泛型用来约束集合中的元素类型,但是只能写引用类型,不能写基本类型
		List<Integer> list = new ArrayList<>();

		list.add(1);
		list.add(2);
		list.add(3);
		list.add(1);
		list.add(2);
		list.add(null);

		// 2,特点:元素有序+允许重复元素,可以存放多个null
		System.out.println(list);

		// 3,调用方法
		// --继承自Collection的方法们
		List<Integer> list2 = new ArrayList<>();
		list2.add(10);
		System.out.println(list.addAll(list2));
		System.out.println(list.contains(10));
		System.out.println(list.isEmpty());
		System.out.println(list.remove(1));
		System.out.println(Arrays.toString(list.toArray()));

		// List的特有方法们--是可以根据下标操作的方法们
		list.add(2, 100);
		System.out.println(list);// 在指定下标处插入指定的元素
		System.out.println(list.get(5));// 获取下标为5的位置对应的元素
		System.out.println(list.indexOf(2));// 获取数字2第一次出现的索引值
		System.out.println(list.lastIndexOf(1));// 获取数字1最后一次出现的索引
		System.out.println(list.remove(3));// 删除下标为3的元素
		System.out.println(list);

		System.out.println(list.set(3, 99));
		System.out.println(list);

		List<Integer> list3 = list.subList(2, 5);
		System.out.println(list3);

		// List的特有方法---迭代List集合
		// Collection接口的方法:Iterator<E> iterator()
		Iterator<Integer> it = list.iterator();
		while (it.hasNext()) {
    
    
			System.out.print(it.next() + " ");
		}
		// List接口的特有方法:ListIterator<E> listIterator()
		ListIterator<Integer> it2 = list.listIterator();
		while (it.hasNext()) {
    
    
			System.out.println(it2.next());
		}

		System.out.println();
		for (int i = 0; i < list.size(); i++) {
    
    
			System.out.print(list.get(i) + "---");
		}
		// 增强for循环 --foreach循环--用来优化普通的for循环,可以用于遍历数组或者collection集合的,好处是高效且语法简洁
		// 语法:for(遍历得到的数据类型 变量名:想要遍历的数组|Collection集合){循环体}
		for (Integer in : list) {
    
    
			System.out.println(in);
		}
	}
}




五、ArrayList实现类

1. 概念

ArrayList是List接口的实现类,可以使用List的功能也可以使用Collection的功能。

2. 特点

  • 底层是一个数组的结构,方便查询。

List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。

3. 创建对象

  • ArrayList()
    构造一个初始容量为 10 的空列表。( jdk1.6)
    - jdk1.6是当创建了一个ArrayList对象时,直接创建一个容量为10的数组;
    - jdk1.8是当创建了一个ArrayList对象时,创建一个空数组。为了优化内存,当第一个元素被添加时,才开始扩充容量。

测试

package cn.tonyoliver.collection;

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

/**
 * 测试ArrayList实现类
 * 
 * @author Tony
 *
 */
public class Test06_ArrayList {
    
    
	public static void main(String[] args) {
    
    
		// 1,创建对象
		ArrayList<Integer> list = new ArrayList<>();

		list.add(1);
		list.add(2);
		list.add(3);
		list.add(1);
		list.add(2);
		list.add(null);

		// 2,调用方法
		// --继承自Collection接口的方法们
		ArrayList<Integer> list2 = new ArrayList<>();
		list2.add(10);
		System.out.println(list.addAll(list2));
		System.out.println(list.contains(10));
		System.out.println(list.isEmpty());
		System.out.println(list.remove(1));
		System.out.println(Arrays.toString(list.toArray()));

		// --继承自List接口的方法们
		list.add(2, 100);
		System.out.println(list);
		System.out.println(list.get(5));
		System.out.println(list.indexOf(2));
		System.out.println(list.lastIndexOf(1));
		System.out.println(list.remove(3));
		System.out.println(list);

		System.out.println(list.set(3, 99));
		System.out.println(list);

		List<Integer> list3 = list.subList(2, 5);
		System.out.println(list3);

		Iterator<Integer> it = list.iterator();
		while (it.hasNext()) {
    
    
			System.out.println(it.next());
		}
		ListIterator<Integer> it2 = list.listIterator();
		while (it2.hasNext()) {
    
    
			System.out.println(it2.next());
		}
		for (Integer it3 : list) {
    
    
			System.out.println(it3);
		}
	}
}

六、LinkedList实现类

1. 概念

是List接口的实现类,同样可以使用List接口和Collection接口的所有方法,也可以进行功能扩展。

2. 特点

  • 底层是链表结构(适合增删)
  • 和List接口一样可以重复,可以有序,可以存null,有下标

3. 创建对象

LinkedList()
构造一个空列表。

4.常用方法

  • void addFirst(E e)
  • void addLast(E e)
  • E getFirst()
  • E getLast()
  • E removeFirst()
  • E removeLast()
  • boolean offerFirst(E e)
  • boolean offerLast(E e)
  • E peekFirst()
  • E peekLast()
  • E pollFirst()
  • E pollLast()
package cn.tedu.api;

import java.util.LinkedList;

/**
 * 这个类用来测试LinkedList
 */
public class Test02_LinkedList {
    
    
    public static void main(String[] args) {
    
    
        //1,创建对象
        LinkedList<Integer> list = new LinkedList<>();
        //2,调用方法
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        //TODO特有方法 -- 对首尾元素的操作
        list.addFirst(100);
        list.addLast(200);

        System.out.println(list.getFirst());//获取首元素
        System.out.println(list.getLast());//获取尾元素
        System.out.println(list.removeFirst());//移除首元素并返回首元素
        System.out.println(list.removeLast());//移除尾元素并返回尾元素
    }
}

七、Set接口

1. 概述

继承自Collection接口,所以可以用父接口Collection的所有方法

2. 特点

  • 元素不能重复,且只能存一个null
  • 元素无序,且没有下标
  • 主要用于去重

3.常用方法

迭代Set集合

package cn.tedu.api;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * 这个类用来测试Set接口
 */
public class Test03_Set {
    
    
    public static void main(String[] args) {
    
    
        //1,创建对象
        Set<Integer> set = new HashSet<>();
        // 特点:Set无序  +  不能重复  +  没有下标  +  存null
        set.add(90);
        set.add(6);
        set.add(56);
        set.add(56);
        set.add(33);
        set.add(null);

        // 迭代Set集合
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()){
    
    
            System.out.println(it.next());
        }
        // for-each 迭代
        for (Integer it2: set) {
    
    
            System.out.println(it2);
         }
    }
}

八、HashSet实现类

1. 概念

是Set接口的实现类,可以使用Set接口的方法;
底层是一个哈希表的结构。

This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over this set requires time proportional to the sum of the HashSet instance’s size (the number of elements) plus the “capacity” of the backing HashMap instance (the number of buckets). Thus, it’s very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.

2.创建对象

HashSet()
构造一个新的空集;支持HashMap实例具有默认的初始容量(16)和加载因子(0.75)。

package cn.tedu.api;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * 这个类用来测试Set接口
 */
public class Test03_Set {
    
    
    public static void main(String[] args) {
    
    
        //1,创建对象
        Set<Integer> set = new HashSet<>();
        // 特点:Set无序  +  不能重复  +  没有下标  +  存null
        set.add(90);
        set.add(6);
        set.add(56);
        set.add(56);
        set.add(33);
        set.add(null);

        // 迭代Set集合
        Iterator<Integer> it = set.iterator();
        while(it.hasNext()){
    
    
            Integer in = it.next();//取数据 + 挪动指针
            //TODO 如果取到null调用null.XXX一定会报空指针异常NullPointerException
            //加一个判断条件可以有效的防止空指针异常
            if(in != null) {
    
    
                System.out.println(in.toString());
            }
        }
        // for-each 迭代
        for (Integer it2: set) {
    
    
            System.out.println(it2);
         }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45015214/article/details/109292953