集合

47 阅读8分钟

1.Collection接口

2. List接口

2.1 ArrayList

2.1.1 常用方法

增add

删remove

改set

查get

package com.qfedu.test2;

import java.util.ArrayList;

/**
 * 	Collection
 * 	List
 * 	ArrayList
 * 
 * 	增add
 * 	删remove
 * 	改set
 * 	查get
 * @author WHD
 *
 */
public class TestArraysList1 {
	public static void main(String[] args) {
		ArrayList list = new ArrayList();
		list.add(20);
		list.add('A');
		list.add("abc");
		list.add("中国");
		
		System.out.println(list.size());
		System.out.println(list.remove(0));
		System.out.println(list.size());
		
		System.out.println(list.set(0, "a"));
		
		System.out.println(list.get(0));
		
		
		System.out.println(list.isEmpty());
		
		list.clear();
		System.out.println(list.isEmpty());
		
		System.out.println(list.size());
	}
}
package com.qfedu.test3;

import java.util.ArrayList;
/**
 * 	泛型 :用于规定集合中的数据类型
 * @author WHD
 *
 */
public class TestArrayList1 {
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<String>(); // ctrl + shift + o
		
		list.add("abc");
//		list.add(20);  类型不匹配
		list.add("hello");
		
		ArrayList<Integer> list1 = new ArrayList<Integer>();
		ArrayList<Boolean> list2 = new ArrayList<Boolean>();
	}
}

2.1.2 遍历

三种方式:

1.普通for循环遍历

2.迭代器遍历

3.增强for循环遍历

package com.qfedu.test3;

import java.util.ArrayList;
import java.util.Iterator;
/**
 * 	集合的遍历
 * 	三种方式:
 * 	1.普通for循环遍历
 * 	2.迭代器遍历
 * 	3.增强for循环遍历
 * @author WHD
 *
 */
public class TestArrayList2 {
	public static void main(String[] args) {
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(20);
		list.add(21);
		list.add(22);
		list.add(23);
		list.add(24);
		
		// 方式1  普通for循环遍历
		for(int i = 0;i < list.size();i++) {
			System.out.println(list.get(i));
		}
		
		System.out.println("-------------------------------");
		
		// 方式2  迭代器遍历
		
		Iterator<Integer> it1 = list.iterator();
		while(it1.hasNext()) {
			System.out.println(it1.next());
		}
		System.out.println("-------------------------------");
		// 方式3 增强for循环 底层实现依然是迭代器 是JDK1.5的新写法  
		
		for(Integer i :list) {
			System.out.println(i);
		}
		System.out.println("-------------------------------");
		int [] nums = {1,2,3,4,5};
		for(int num : nums) {
			System.out.println(num);
		}
	}
}

2.1.3 底层实现

ArrayList特点:

有序,可以重复,可以为null,线程不安全

底层实现是一个Object类型的数组

当我们调用无参构造方法,底层维护一个空数组,当我们第一次添加元素,将数组的长度改为10

扩容为原数组的1.5倍

查询,修改快,因为有下标

增加慢,因为需要扩容

删除慢,因为需要移动元素

2.2 Vector

Vector类 和ArrayList的区别?

Vector是线程安全的  JDK1.0

ArrayList线程不安全 JDK1.2

Vector调用无参构造直接初始化一个长度为10的数组

ArrayList调用无参构造初始化一个空数组

ArrayList扩容1.5倍

Vector扩容两倍

package com.qfedu.test5;

import java.util.Vector;
/**
 * 	Vector类 和ArrayList的区别?
 * 		Vector是线程安全的  JDK1.0
 * 		ArrayList线程不安全 JDK1.2 
 * 		Vector调用无参构造直接初始化一个长度为10的数组
 * 		ArrayList调用无参构造初始化一个空数组
 * 		ArrayList扩容1.5倍
 * 		Vector扩容两倍
 * 	
 * @author WHD
 *
 */
public class TestVector {
	public static void main(String[] args) {
		Vector<Double> v1 = new Vector<Double>();
		v1.add(2.2);
		v1.add(2.3);
		v1.add(2.5);
		v1.add(20.1);
		
		System.out.println(v1.size());

		System.out.println(v1.remove(0));
		
		v1.set(0, 220.2);
		
		System.out.println(v1.get(0));
		
		System.out.println(v1.isEmpty());	
		
		v1.clear();
		
		System.out.println(v1.isEmpty());	
		// 遍历方法 和ArrayLis相同  有三种
	}
}

2.3 LinkedList

2.3.1 常用方法

LinkedList 基于双向链表实现的集合

除了与ArrayList相同的增删改查方法以外

还单独提供了用于操作头部和尾部的方法

package com.qfedu.test6;

import java.util.LinkedList;

/**
 * 	LinkedList 基于双向链表实现的集合
 * 	除了与ArrayList相同的增删改查方法以外
 * 	还单独提供了用于操作头部和尾部的方法
 * @author WHD
 *
 */
public class TestLinkedList {
	public static void main(String[] args) {
		LinkedList<String> list = new LinkedList<String>();
		list.add("a");
		list.add("b");
		list.addFirst("hello");
		list.addFirst("C");
		list.addLast("xyz");
		
		System.out.println(list.size());
		
		System.out.println(list.getFirst());
		System.out.println(list.getLast());
		System.out.println(list.get(2));
		
		System.out.println(list.remove(0));
		
		System.out.println(list.set(0, "HELLO"));
		
		System.out.println(list.removeFirst());
		
		System.out.println(list.removeLast());
		
		list.clear();
		
		System.out.println(list.isEmpty());
	}
}

2.3.2 遍历

LinkedList三种遍历方式

1.普通for循环

2.迭代器

3.增强for循环

package com.qfedu.test6;

import java.util.Iterator;
import java.util.LinkedList;

/**
 * 	LinkedList三种遍历方式
 * 	1.普通for循环
 * 	2.迭代器
 * 	3.增强for循环
 * @author WHD
 *
 */
public class TestLinkedList1 {
	public static void main(String[] args) {
		LinkedList<Integer> list = new LinkedList<Integer>();
		
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		// 方式1
		for(int i = 0;i < list.size();i++) {
			System.out.println(list.get(i));
		}
		System.out.println("-----------------------------");
		// 方式2
		Iterator<Integer> it = list.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
		System.out.println("-----------------------------");
		// 方式3
		for(Integer i : list) {
			System.out.println(i);
		}
	}
}

2.3.3 底层实现

LinkedList特点:

有序的,允许重复,允许为null,线程不安全

根据下标查询,修改慢,因为不能直接查询到某个元素,必须先查询到相邻元素

增加和删除快,因为不需要扩容,不需要移动元素

get()方法优化:当我们根据下标查找LinkedList元素的时候

先对下标进行判断,如果下标是小于集合总长度中间值的 ,从前往后查询

否则,从后往前找

鉴于LinkedList数据结构特点,不要使用普通for循环遍历

3. Collections

针对集合提供的工具类

常用方法:
sort() 排序
binarySearch() 二分查找
max() 最大值
min() 最小值
reverse() 反转
shuffle() 乱序

3.1 排序

List<Integer> list = new ArrayList<Integer>();
		list.add(10);
		list.add(12);
		list.add(6);
		list.add(8);
		list.add(30);
		list.add(23);
		
		// 排序
		Collections.sort(list);
		System.out.println(list);
		
		// 第二个参数 比较器(两种方式:1 自定义类实现Comparator接口, 2匿名内部类)
		Collections.sort(list, new MyComparator());
		System.out.println(list);
		
		// 匿名内部类,
		// 针对接口、抽象类,不需要实现类
		// new 接口名/抽象类名(){ 重写的方法 }
		Collections.sort(list, new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				// TODO Auto-generated method stub
				return o2 - o1;
			}});
		System.out.println(list);

3.2自定义类排序

		List<Student> stuList = new ArrayList<Student>();
		Student s1 = new Student(10, "zhangsan", 20);
		Student s2 = new Student(9, "lisi", 10);
		Student s3 = new Student(45, "lisiw", 25);
		Student s4 = new Student(23, "gousheng", 12);
		Student s5 = new Student(26, "liuneng", 40);
		stuList.add(s1);
		stuList.add(s2);
		stuList.add(s3);
		stuList.add(s4);
		stuList.add(s5);
		
		Collections.sort(stuList, new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				// TODO Auto-generated method stub
				return o1.getAge() - o2.getAge();
			}
		});
		
		// System.out.println(stuList);
		for(Student stu : stuList) {
			System.out.println(stu);
		}
		
		System.out.println("---------------------------------");
		Collections.sort(stuList, new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				// TODO Auto-generated method stub
				// 字符串中compareTo,比较字符串大小,比如s1, s2, 如果s1大于s2,返回1;s1等于s2,返回0;s1小于s2,返回-1 
				return o1.getName().compareTo(o2.getName());
			}
		});
		
		for(Student stu : stuList) {
			System.out.println(stu);
		}

3.3 二分查找

		List<Integer> list = new ArrayList<Integer>();
		list.add(10);
		list.add(12);
		list.add(6);
		list.add(8);
		list.add(23);
		
		// 6 8 10 12 23
		Collections.sort(list);
		System.out.println(list);
		// 二分查找 针对有序的集合
		int index = Collections.binarySearch(list, 12);
		System.out.println(index);

3.4 其他

		List<Integer> list = new ArrayList<Integer>();
		list.add(10);
		list.add(12);
		list.add(6);
		list.add(8);
		list.add(23);
		
		// 找最大值
		Integer max = Collections.max(list);
		System.out.println(max);
		
		// 乱序
		Collections.shuffle(list);
		System.out.println(list);

		// 反转
		Collections.reverse(list);
		System.out.println(list);

4. Map接口

4.1 HashMap

4.1.1 常用方法

put()

remove()

get()

size()

clear()

replace()

package com.qfedu.test1;

import java.util.HashMap;

/**
 * 	Map
 * 	HashMap
 * 
 * 	put()
 * 	remove()
 * 	get()
 * 	size()
 * 	clear()
 * 	replace()
 * @author WHD
 *
 */
public class TestHashMap {
	public static void main(String[] args) {
		HashMap<String,String> map = new HashMap<String,String>();
		
		map.put("CN", "中国");
		map.put("US", "美国");
		map.put("RU", "俄罗斯");
		map.put("KR", "棒子");
		map.put("JP", "小日本");
		
		System.out.println(map.size());
		
		map.replace("JP", "鬼子");
		
		System.out.println(map.get("JP"));
		
		System.out.println("删除了:" + map.remove("JP"));
		
		System.out.println(map.size());
		
		
		map.clear();
		
		System.out.println(map.isEmpty());
	}
}

4.1.2 遍历

1.获取所有的键

2.获取所有的值

3.获取所有的键和值的组合

4.获取所有键的迭代器

5.获取所有值的迭代器

6.获取所有的键和值的组合的迭代器

package com.qfedu.test1;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 	HashMap集合遍历
 * 
 * 	1.获取所有的键
 * 	2.获取所有的值
 * 	3.获取所有的键和值的组合
 * 
 * 	4.获取所有键的迭代器
 * 	5.获取所有值的迭代器
 * 	6.获取所有的键和值的组合的迭代器
 * @author WHD
 *
 */
public class TestHashMap1 {
	public static void main(String[] args) {
		HashMap<String,String> map = new HashMap<String,String>();
		map.put("CN", "中国");
		map.put("US", "美国");
		map.put("RU", "俄罗斯");
		map.put("KR", "棒子");
		map.put("JP", "小日本");
		
		// 方式 1
		Set<String> keySet = map.keySet();
		for(String key : keySet) {
			System.out.println(key + "====" + map.get(key));
		}
		System.out.println("-------------------------------------");
		
		// 方式2 
		Collection<String> values = map.values();
		for(String v : values) {
			System.out.println(v);
		}
		System.out.println("-------------------------------------");
		// 方式3 
		Set<Entry<String, String>> entrySet = map.entrySet();
		for(Entry<String,String> entry : entrySet) {
			System.out.println(entry.getKey() + "===" + entry.getValue());
		}
		System.out.println("-------------------------------------");
		// 方式4
		Iterator<String> it1 = map.keySet().iterator();
		while(it1.hasNext()) {
			String key = it1.next();
			System.out.println(key + "====" +map.get(key));
		}
		System.out.println("-------------------------------------");
		// 方式5
		Iterator<String> it2 = map.values().iterator();
		while(it2.hasNext()) {
			System.out.println(it2.next());
		}
		System.out.println("-------------------------------------");
		// 方式6
		Iterator<Entry<String, String>> it3 = map.entrySet().iterator();
		
		while(it3.hasNext()) {
			Entry<String,String> entry = it3.next();
			System.out.println(entry.getKey() + "===" + entry.getValue());
			// System.out.println(it3.next());
		}
	}
}

4.1.3 数据结构

回顾之前所学习的数据结构

ArrayList:数组 因为有下标 所以查询快 修改快    删除、增加慢

LinkedList:双向链表 因为没有下标 (有序,有序号) 所以 删除、增加快 ,查询快 修改慢

HashMap数据结构:

JDK1.7 数组 + 单向链表

JDK1.8 数组 + 单向链表 + 红黑树

HashMap存放元素过程:根据key所计算出来的hash值,决定当前元素在数组的位置,

如果当前位置没有元素,则直接存放

如果当前位置有元素,则向下延伸为单向链表,如果单向链表的长度超过8,将转换为红黑树

后续链表以后的元素减少到6以下,再将红黑树转换为单向链表

扩容当数组的使用率达到75%  并且集合中的元素个数大于64  扩容2倍

4.2 Hashtable

HashMap 与Hashtable区别?

Hashtable线程安全  初始数组长度11 扩容2倍 + 1

HashMap线程不安全  初始数组长度16 扩容2倍

4.3 泛型

泛型:用于规范集合,或者接口,类中的数据类型

泛型书写位置:

接口上

形参

返回值

泛型通用的字母:

T Type 类型

E Element 元素

R Return 返回值

P Parameter 参数

K Key 键

V Value 值

package com.qfedu.test4;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * 	泛型:用于规范集合,或者接口,类中的数据类型
 * 
 * 	泛型书写位置:
 * 		类
 * 		接口上
 * 		形参
 * 		返回值
 * 
 * 	泛型通用的字母:
 * 	T	Type		类型
 * 	E	Element		元素
 * 	R	Return		返回值
 * 	P	Parameter	参数
 * 	K	Key			键
 * 	V	Value		值
 * @author WHD
 *
 */
public class Test1 {
	public static void main(String[] args) {
		A<String> a = new A<String>();
		
		a.m1("abc");
		a.m2();
		
		A<Integer> a1 = new A<Integer>();
		a1.m1(20);
		a1.m2();
		
		
		A<Boolean> a2 = new A<Boolean>();
		a2.m1(false);
		a2.m2();
		
		
		B1 b1 = new B1();
		b1.m1("a");
		B2 b2 = new B2();
		b2.m1(3.14F);
	}
}
class Pet{}

class Dog extends Pet{}

class Penguin extends Pet{}


class TestPet{
	public static void m1(List<? extends Pet> list) {
		
	}
	
	
	public static void m2(Set<? super Dog> set) {
		
	}
	
	
	public static void main(String[] args) {
		ArrayList<Dog> list1 = new ArrayList<Dog>();
		ArrayList<Penguin> list2 = new ArrayList<Penguin>();
		LinkedList<Pet> list3 = new LinkedList<Pet>();
		m1(list1);
		m1(list2);
		m1(list3);
		
		Set<Dog> set1 = new HashSet<Dog>();
		Set<Pet> set2 = new HashSet<Pet>();
		m2(set1);
		m2(set2);
	}
}

interface C<P,R>{
	R m1(P p);
}

class C1 implements C<String,Integer>{

	@Override
	public Integer m1(String p) {
		return null;
	}
}

class C2 implements C<Double,Character>{

	@Override
	public Character m1(Double p) {
		return null;
	}
	
}

class A<T>{
	void m1(T t) {
		System.out.println(t);
	}
	
	T m2() {
		return null;
	}
	
	public static <T> void m3(T t) {
		List<T> list = new ArrayList<T>();
	}
}

interface B<E>{
	E m1(E e);
}

class B1 implements B<String>{

	@Override
	public String m1(String e) {
		return null;
	}
}

class B2 implements B<Float>{

	@Override
	public Float m1(Float e) {
		return null;
	}
}

5. Set

5.1 HashSet 重点

无序 元素唯一

常用方法: add
remove
循环遍历

public class App {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		HashSet<String> hashSet = new HashSet<String>();
		hashSet.add("nvwangjie");
		hashSet.add("xiannvjie");
		hashSet.add("xiannvjie");
		hashSet.add("nvshenjie");
		hashSet.add("laodongjie");
		hashSet.add("chunjie");
		
		// 增加的for循环
		for(String s : hashSet) {
			System.out.println(s);
		}
		
		// 迭代器
		Iterator<String> iterator = hashSet.iterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
}

向set中添加数据时,如何判断两个对象是否相同(笔试、面试中)

  • 先判断hashCode(), 如果hashCode()返回的值一样,再判断equals()
public class App2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		HashSet<Student> stuSet = new HashSet<Student>();
		Student s1 = new Student(1, "gousheng", 20);
		Student s2 = new Student(2, "wangcai", 10);
		Student s4 = new Student(2, "wangcai", 10);
		Student s3 = new Student(3, "fugui", 20);
		
		stuSet.add(s1);
		stuSet.add(s2);
		stuSet.add(s3);
		stuSet.add(s4);
		
		for(Student s : stuSet) {
			System.out.println(s.getName() + "-" + s.getAge());
		}
		
	}

}


public class Student {
	
	private int id;
	
	private String name;
	
	private int age;
	
	public Student() {
	}

	public Student(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	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 int hashCode() {
		// TODO Auto-generated method stub
		return this.name.hashCode();
	}
	
	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		Student s = (Student)obj;
		return this.name.equals(s.getName());
	}
	
	
}

5.2 TreeSet 知道

内部进行排序、 元素唯一

红黑树

public class App3 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TreeSet<Integer> treeSet = new TreeSet<Integer>();
		treeSet.add(10);
		treeSet.add(20);
		treeSet.add(5);
		treeSet.add(12);
		treeSet.add(8);
		
		for(Integer i : treeSet) {
			System.out.println(i);
		}
	}
}

内部类

针对接口、抽象类,不需要实现类

语法格式:new 接口名/抽象类名(){ 重写的方法 }

使用参考排序的代码