JAVA类集

声明:学基础,在校学生,本文所有内容来自书本和视频,然后通过自己的理解和筛选编写而来,如有理解不到位的写得不到位的地方,欢迎评论指错!!!(仅做学习交流)
笔者:Fhvk
微信:WindowsC-

数组存储对象案例

public class Demo_Array {
	public static void main(String[] agrs) {
		Student[] arr = new Student[5];
		arr[0] = new Student("李超武", 19);
		arr[1] = new Student("陈清香", 20);
		arr[2] = new Student("阳文杰", 21);
		for(Student stu : arr) {
				System.out.println(stu);  //调用toString()方法
		}
	}
}
  • 数组中存放的是地址
    在这里插入图片描述

为什么要有集合&&集合和数组的区别&&集合体系图

  • 为什么要有集合?因为数组的特点是长度固定,当添加元素超过了数组长度就要重新定义更大数组,JAVA内部给我们提拱了集合类,能存储任意对象,长度可变,随着元素增加而增加,随着元素减少而减少;
  • 数组和集合的区别:
    1、数组可以存储基本数据类型和引用数据类型,而集合只能存储引用数据类型(基本数据类型包装类)
    2、数组长度是固定,集合长度是可变,随增就增,随减就减;
  • 数组和集合什么时候用?
    1、如果元素个数固定的使用数组
    2、如果元素个数不固定使用集合
  • 体系图

Collection集合的基本功能

在这里插入图片描述

  • 注意:add()方法在List和Set中都有返回boolean;在List中永远返回的是true,因为List中永远都存储得了重复的元素,Set中如果出现重复的元素就会返回false;从源码中可以看到;

集合遍历之数组遍历(知道就好)

  • 这个知识点了解就好,后面会讲迭代器
  • 就是通过toArray()方法返回该集合的数组形式,接收的是Object[];
public class Demo {
	public static void main(String[] agrs) {
		Collection<Integer> c = new ArrayList<Integer>();
		c.add(1); //不是说只能存对象?而且泛型指定了Integer;这里应用到自动装箱;
		c.add(2);
		c.add(3);
		Object[] arr = c.toArray();
		for(Object obj : arr) {
				System.out.println((Integer)obj);
		}
	}
}

集合中带All的功能

public class Demo_CollectionAll {
	public static void main(String[] agrs) {
		Collection c1 = new ArrayList();
		c1.add("a");
		c1.add("b");
		c1.add("c");
		c1.add("d");
		
		Collection c2 = new ArrayList();
		c2.add("a");
		c2.add("b");
		c2.add("c");
		c2.add("d");

		c1.addAll(c2);   //将c2集合中的元素添加c1集合中
		c1.add(c2); 	//将c2集合对象添加到c1集合中,以toString()

		c1.removeall(c2);  //删除交集,删除c1中和c2中元素一样的元素

		c1.containsAll(c2);   //判断c1中是否包含c2集合,包含返回true,不包含返回false

		c1.retainAll(c2); //取交集,取出c1和c2中共同的元素;改变的是c1;返回boolean
	}
}

集合迭代器(遍历)

  • 集合是用来存储元素的,存储元素需要查看,那么就需要迭代(遍历)
  • Iterator中三个抽象方法
    1、hasNext();如果仍有元素可以迭代,则返回true;
    2、next();返回迭代下一个元素;
    3、remove();删除当前元素;
public class Demo_Iterator {
	public static void main(String[] agrs) {
		Collection c = new ArrayList();
		c.add(new Student("李超武", 19, 60.1));
		c.add(new Student("吴非凡", 20, 65.1));
		Iterator it = c.iterator();   //获取迭代器
		while(it.hasNext()) {    //判断集合中是否有元素,有返回true,没有返回false;
			Student stu = (Student)it.next();
			System.out.println(stu.getName());
		}
	}
}
  • 1、Iterator接口的功能是从前向后输出,属于单向的输出;
  • 2、Iterator主要的是功能就是完成迭代输出操作;
  • 3、在使用Iterator时候不要删除数据,换修改数据;

迭代器原理分析

  • 为什么要把hasNext()、next()这样的方法向上抽取到接口?
  • 迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同,所以每一个集合的存和取都是不一样的,那么就需要在每一个类中定义hasNext和next方法,这样做是可以的,但是会让整个集合体系过于臃肿,迭代器是将这样的方法向上抽取到接口,然后在每个类的内部,定义自己迭代方式,这样做的好处有二种:第一规定整个集合体系的遍历方式都是hasNext和next方法,第二代码由底层内部实现,使用者不用管怎么实现的,会用就可以了;
  • 怎么实现的?进去去看源码ArrayList中iterator()方法发现返回的是Itr类实现了Iterator接口,重写了所有方法;代码实现自己理解;

Collection接口的子接口List

  • List集合特有的功能
public class Demo_List {
	public static void main(String[] agrs) {
		List list = new ArrayList();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(2, 8); //指定位置添加元素
		list.remove(1); //指定位置删除元素
		list.get(1); //指定位置获取元素
		list.set(1, 200);//指定位置获取元素

		//	通过get()方法遍历
		for(int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}
}

在这里插入图片描述

  • 在List集合中存储学生对象并遍历
public class Test {
	public static void main(String[] agrs) {
		List list = new ArrayList();
		list.add(new Student("李超武", 19));
		list.add(new Studnet("吴非凡", 20));
		for(int i = 0; i < list.size(); i++) {
			Student stu = (Student)list.get(i);
			System.out.println("学生姓名为: " + stu.getName()):
		}
	}
}

并发修改异常的解决方法

//	在遍历的同时修改集合元素
public class Demo_Listiterator {
	public static void main(String[] agrs) {
		List list = new ArrayList();
		list.add("a");
		list.add("b");
		list.add("c");
		ListIterator ite = list.listIterator();
		while(ite.hasNext()) {
			if(ite.next().equals("c")) {
					ite.add("d");   //通过ListIterator中的方法
			}
		}
		System.out.println(list);
 	}
}

ListIterator

public class Demo_ListIterator {
	public static void main(String[] agrs) {
		List list = ArrayList();
		list.add("a");
		list.add("b");
		list.add("c");
		ListIterator lte = list.listIterator();
		while(ite.hasNext()) {
			System.out.print(ite.next());
		}
		//注意指针一定要指向最后一个元素,否则如果是从一开始遍历,那么一直都是false
		while(ite.hasPrevious()) {     //指针向前移,反着遍历
			System.out.print(ite.pevious());  //返回上一个元素
		}
	}
}
  • 注意:1、如果要想使用ListIterator则只能依靠List接口完成;
    2、如果要进行由后向前输出,则只能先进行由前向后输出;
    3、对于此接口中的增加及修改操作了解就好;

Vector

  • 从jdk1.2此类改进实现了List接口
public class Demo_Vector {
	public static void main(String[] agrs) {
		Vector v = new Vector();
		v.addElements("a");
		v.addElements("b");
		v.addElements("c");
		Enumeration e = v.elements();
		while(e.hasMoreElements()) {
			System.out.println(e.nextElement());
		}
	}
}
  • 1、在所有的输出操作中,以Iterator接口为最标准的输出操作,这一点一定要记住;
  • 2、在部分旧的操作中Enumeration依然存在,限制在Vector集合中;

数据结构之数组和链表

  • 简单说下
  • 数组:查询快,增删慢;
  • 链表:查询慢,增删快;
  • 都是相对的,自己看下源码;

List的三个子类的特点

  • ArrayList:底层是数组实现的;查询快,增删慢;线程不安全,效率高;
  • Vector:底层是数组实现;查询快,增删慢;线程安全的;效率低;
  • Vector相对ArrayList查询慢点(线程安全的)
  • Vector相对是LinkedList增删慢(数据结构)
  • LinkedList:底层是链表实现的;增删快,查询慢;线程不安全的效率高
  • Vector和ArrayList的区别:Vector是线程安全的;效率底,ArrayList是线程不安全的,效率高;
  • ArrayList和LinkedList的区别:ArrayList底层数组实现,查询修改快;LinkedList底层是链表实现的,增删快,查询和修改相对慢;
  • 查询多用ArrayList,增删多用LinkedList,如果都多用ArrayList;

去除ArrayList中重复字符串的方式

public class Demo_ArrayList {
	public static void main(String[] agrs) {
		ArrayList list = new ArrayList();
		list.add("a");
		list.add("a");
		list.add("b");
		list.add("b");
		ArrayList newList = getSingle(list);
	}
	//这下面有错误,观察next()方法
	public static ArrayList getSingle(ArrayList list) {
		ArrayList newList = new ArrayList();
		Iterator ite = list.iterator();
		while(ite.hasNext()) {
			if(!newList.contains(ite.next))  {
				newList.add(ite.next());
			}
		}
	}	
 }

去除ArrayList中重复自己定义对象

  • 如果是自定义对象,就必须重写equals()方法,因为contains()方法和remove()方法底层都是通过equals()方法进行判断的。上面字符串String底层重写equals()方法
//比如我要去除重复自定义对象,如果不重写equals()方法。就继承自Object中的equals()方法,那么方法比较的就是地址值;所以必须重写比较属性
public class Demo_Student {
	public static void main(String[] agrs) {
		ArrayList list = new ArrayList();
		list.add(new Student("李超武", 19));
		list.add(new Student("陈清香", 20));
		list.add(new Student("李超武", 19));
		list.add(new Student("陈清香", 20));
		ArrayList newList = getSingle();
		System.out.println(newList);
	}
	public static ArrayList getSingle(ArrayList list) {
		ArrayList newList = new ArrayList();
		Iterator ite = list.iterator();
		while(ite.hasNext()) {
			Object obj = ite.next();
			if(!newList.contains(obj)) {
				newList.add(obj);
			}
		}
	}
}

LinkedList特有的功能

在这里插入图片描述

数据结构之栈和队列

  • 简装说一下
  • 栈:先进后出
  • 队列: 先进先出

用LinkedList模拟栈数据结构的集合并测试

//单独写个类
public class Stack {
	private LinkedList  list  = new LinkedList();
	//进栈方法
	public void in(Object obj) {
		list.addLast(obj);
	} 
	//出栈
	public Object out() {
		return list.removeLast();
	}
	//判断栈是否为空
	public boolean isEmpty() {
		return list.isEmpty();
	}
}
//测试类
public class Test {
	public static void main(String[] agrs) {
		Stack s = new Stack();
		s.in("a");
		s.in("b");
		s.in("c");
		while(s.isEmpty()) {
			System.out.print(s.out());
		}
	}
}

注意:实现队列同理,修改remove就可以;

jdk1.5新特性增强for的使用

  • 简化数组和Collection集合的遍历,底层是Iterator(迭代器实现的);
//数组
in[] arr = {11, 22, 33, 44};
for(int i : arr) {
	System.out.println(i);
}
//集合
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
for(String string : list) {
	System.out.println(string);
}

集合中三种删除的遍历

//普通for循环,删除后要减减,因为集合每删除一个元素都会自动向前移
for(int i = 0; i < list.size(); i++) {
	if(list.get(i).equals("b")) {   //集合中元素为b的删除
		list.remove(i);
		i--;   //i一定要减减
	}
}
//Iterator遍历,删除不能使用集合中remove中的删除方法,因为会出现并发修改异常;要使用Iterator中的remove方法
Iterator<String> ite = list.iterator(); 
while(ite.hasNext()) {
	if("b".equals(ite.next)) {
		ite.remove();
	}
}
System.out.println(list);
//增强for循环,不能实现删除,肯定会出现并发修改异常,因底层是Iterator;而且又没有Iterator的引用,只能使用集合删除,异常是必须的;
for(String string : list) {
	if(string.equals("b")) {
		list.remove(string);   //错
	}
}

jdk1.5新特性静态导入

  • 开发不用,知道就好
  • 注意事项:方法必须是静态的,如果有多个同名的静态方法,容易不知道使用哪个,必须加前缀,由此义意不大,所以不用,但要能看得懂;
  • Arrays里所有的类都是静态的
import static java.util.Arrays.sort;   //导入排序方法,该源文件下所有的sort()方法不用加Arrays.

jdk1.5新特性可变参数(数组)

  • 定义方法的时候,不知道定义多少个参数;
  • 使用方法
public class Demo {
	public static void main(String[] agrs) {
		int[] arr = {1,2,3,4,5,6};
		print(arr);
	}
	public static void print(int x, int ... arr) {  //可变参数使用格式.其实就是一个数组
		for(int i : arr) {
			System.out.print(i + " ,");
		}
	}
}
输出:2,3,4,5,6;  为什么没有1?因为1给了x;没有打印
注意事项:多个参数时,可变参数必须放后面; 

Arrays工具类中asList()方法

  • asList()方法:数组转成集合;
  • 注意事项:
    1、数组转集合虽然不能添加和删除,但可以用集合思想操作数组,其它方法可以使用;
    2、基本数据类型的数组如果通过asList()方法转成集合的话,会将整个数组当成一个对象转为集合;所以将数组转成集合,数组必须是引用数据类型
//数组转集合
public class Demo {
	public static void main(String[] agrs) {
		//引用数据类型
		String[] arr = {"a", "b", "c"};
		List<String> list = Arrays.asList(arr);
		System.out.println(list);
	}
}
//集合转数组
public class Demo {
	public static void main(String[] agrs) {
		ArrayList<String> list = new ArrayList<>();
		list.add("a");
		list.add("b");
		//[0]给数组大小,但如果集合size的大小大于数组大小,那数组也会增大和集合一样大,如果数组大小大于集合,集合中的元素赋给数组,多于的大小全为null;
		String[] arr = list.toArray(new String[0]);
		for(String string : arr) {
			System.out.println(string);
		}
	}
}

集合中套集合并遍历

public class Demo {
	public static void main(String[] agrs) {
		ArrayList<ArrayList<Person>> list = new ArrayList<>();

		ArrayList<Person> stu1 = new ArrayList<>();
		stu.add(new Person("S1", 19));
		stu.add(new Person("S2", 20));
		ArrayList<Person> su2 = new ArrayList<>();
		stu.add(new Person("A1", 40));
		stu.add(new Person("A2", 50));

		list.add(stu1);
		list.add(stu2);
		for(ArrayList<Person> stu : list) {
			for(Person p : stu) {
					System.out.println(p);
			}
		}
	}
}

HasSet

  • Collection子接口Set的特点:不能存储重复元素,没有索引,存和取无序,没有啥特有方法和Collection中方法一样,不同的是add()方法可以返回false,当存储重复元素时返回false,不能用普通for循环遍历;1、没有get()方法;2、无序没索引,只能Iterator;
  • 如下:
public static void main(String[] agrs) {
	HashSet<String> has = new HashSet<>();
	has.add("a");
	has.add("b");
	//当然也可以增强for,底层都是Iterator
	Iterator<String> ite = has.iterator();
	while(ite.hasNext()) {
		System.out.println(ite.next());
	}
}

存储自定义对象如何保证元素唯一性

  • 自定义对象必须重写hashCode()方法和equals()方法,作用:去除重复对象;
  • 我们使用Set集合都是要去除重复元素的,如果在存储的时候逐个equals()比较,效率太低,哈希算法提高了去重复的效率,降低了使用equals()方法次数;
  • 当HashSet调用add()方法时,先调用对象的HashCode()方法得到一个哈希值,然后在集合中查找是否有哈希值相同的对象;
    1、如果没有哈希值相同的对象就直接存入集合;
    2、如果有哈希值相同的对象,就和哈希值一样的对象逐个进行equals()方法进行比较,结果fasle进行存入,true则不存
  • hashCode():返回的是一个int类型的只希值,如果集合中有一样的,就会调用equals()运行比较,如果返回值int哈希值不一样,直接存入集合中;
  • equals():属性相同返回true,不同返回false;
//自己重写
public boolean equals(Object obj) {
	Person p = (Person)obj;
	return p.name.equals(this.name) && p.age == this.age;
}
//尽量减少调用equals()
public int hashCode() {
	final int NUM = 38;
	return name.hashCode() * 38 + age;
}
//Eclipase生成的
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + age;
	result = prime * result + ((name == null) ? 0 : name.hashCode());
	return result;
}
public boolean equals(Object obj) {
		if(this == obj) {
			return true;
		}
		if(obj == null) {
			return false;
		}
		if(getClass() != obj.getClass()) {
			return false;
		}
		Person other = (Person)obj;
		if(age != other.age) {
			return flase;
		}
		if(name == null) {
			if(other.name == null) {
				return false;
			}
		}else if(!name.equals(other.name)) {
			return false;
		}
		return true;
}

LinkedHashSet

  • 是HashSet的子类,所以原理和HashSet一样,但因为是链表实现所以可以保证怎么存怎么取;
public class Demo {
	public stataic void main(String[] agrs) {
		LinkedHashSet<Integer> lhs = new LinkedHashSet<>();
		lhs.add("a");
		lhs.add("b");
		lhs.add("b"):
		System.out.println(lhs);
	}
}

TreeSet

  • 特点:保证元素唯一,并且是可以排序的;
  • 如果保证自定义对象的唯一和排序:实现Comparato接口,并重写里面的compareTo()方法;方法返回正数放左边,返回负数放右边,返回0不存;
    1 、返回0:集合中只有一个元素
    2、返回-1:集合会倒序;
    3、返回1:集合存怎怎取;
//Integer包装重写了compareTo()方法,所以具有自动排序功能
public class Demo {
	public static void main(String[] agrs) {
		TreeSet<Integer> ts = new TreeSet<>();
		ts.add(23);
		ts.add(21);
		ts.add(25);
		System.out.println(ts);   //输出21 23 25;		
	}	
}

TreeSet自定义对象如何进行排序

  • 重写compareTo()方法:下面用一个学生类做比较
    在这里插入图片描述

TreeSet使用比较器实现排序(Comparator)

  • TreeSet有参构造中可以传入一个比较器多象,比较器是个接口,先实现它,并重写compare()方法,原理和compareTo()方法一样;该接有两个方法一个compare()一个equals(),equals()方法不用你重写会默认继承Object中的equals();
class CompareByLen imelements Comparator<Student> {
	//按照姓名长度,进行排序,如果长度一样,名字不一样,按照姓名排序;如果名字长度和姓名都一样就按年龄排序
	public int compare(Student o1, Student 02) {
		int num = o1.getName().length() - o2.getName().length();
		return num == 0 ? o1.getName().equals(o2.getName()) ? o1.getAge() - o2.getAge() : o1.getName().compareTo(o2.getName()) : num;
	}
}

TreeSet总结

  • 特点:TreeSet是可以用来排序的集合,可以指定一个顺序,对象存入之后会按指定的顺序排列;有两种方法实现排序

  • 自然排序:1、对象必须实现Comparable接口,然后重写compareTo()方法
    2、TreeSet类的add()方法中会将存入的对象提为Comparable
    3、然后调用对象的compareTo()和集合中的对象进行比较
    4、根据compareTo()方法返回的结果进行存储; 1右,-1左,0不存;

  • 比较器排序:1、创建一个类实现Comparator接口,重写compare()方法,然后通过匿名内部类将Comparator传给TreeSet有参构造,该集合就会按照比较器排序;
    2、add()方法会自动调用compare()方法;3、compare()方法中有两个参数,第一个对象是自己,第二个对象是集合中的对象;

  • 两种方法的区别:如果按照自然排序,就必须实现Comparable重写compareTo()方法,否则什么都不写,就会报错(ClassCastException);但是如果两次方法都实现了,优先比较器;

SortedSet接口

  • TreeSet是可以排序的操作类,TreeSet实际上也是SortedSet接口的子类,些接口所有的类都是可以排序的;
  • SortedSet中定义的方法
    在这里插入图片描述
  • 注意:只要是以Sorted开头的接口,基本上都是表示可以排序的接口;所有实现类都可以排序都是通过Comparable实现的;

Map集合

  • 一个键对应一个值
  • map集合和Collection接口的区别
    map是双列集合,它是双列集合的根接口;
    Collection是单列集合,它时单列集合的根接口;
    map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效;
    单列集合底层依赖的map集合

Map集合的功能概述

  • 添加功能
public class Demo {
	public static void main(String[] agrs) {
		Map<String, Integer> m = new HashMap<>();
		m.put("张三", 23);    //返回null
		m.put("李四", 24);    //返回 null
		m.put("王五", 25);     //返回null
		m.put("张三", 26);      //返回23,键是唯一的,它就会把原来的值覆盖掉,返回被覆盖的值;
		System.out.println(m); 
	}
}
  • 删除功能
    clear();删除所有的键和值元素
    remove(Object key);通过键删除元素,并把值返回;

  • 判断功能
    containsKey(Object key);判断是否包含这个键
    containsValue(Object value);判断是否包含这个值
    isEmpty()判断是否为空;

  • 获取功能
    Set<Map.Entry<k, v>> entrySet();拿到所有的键值对象;
    V get(Objetc key);根据键获取值;
    Set keySet();获取该集合所有的键;
    Collection values();获取集中所有的值;

  • 长度功能
    int size();返回集合中元素个数;

Map集合的遍历(通过键找值)

  • API可以看出双集合没有iterator方法,那么双列如何迭代呢?
//迭代器
public class Dmeo {
	public static void main(String[] agrs) {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		//获取所有键,返回一个Set集合
		Set<String> keyset= map.keySet();
		Iterator<String> ite = keyset.iterator();
		while(ite.hasNext()) {
			String key = ite.next;
			Integer value = map.get(key);
			System.out.println("key : " + key + ", value : " + value );
		}
	}
}
//增强for循环
public class Demo {
	public static void main(String[] agrs) {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三" , 23);
		map.put("李四", 24);
		for(String string : map.keySet()) {
			System.out.println("key  : " + string + " , value : " + map.get(string));
		}
	}
}

Map集合的遍历(通过键值对象找键和值)

  • 通过entrySet()方法获取集合中所有的键值对象;这个键值对象是Map接口中的内部接口,Map.Entry<Key, Value>;该接口中有getKey()和getValue()可以获取键和值;
//迭代器遍历
public class Demo {
	public static void main(String[] agrs) {
		Map<String, Integer> map = new HashMap<>();
		map.put("李超武", 10);
		map.put("张三", 20);
		//获取map集合中所有的键值对对象,返回给Set集合;
		Set<Map.Entry<String, Integer>> entry = map.entrySet();
		//获取迭代器
		Iterator<Map.Entry<String, Integer>> ite = entry.iterator();
		while(ite.hasNext()) {
			Map.Entry<String, Integer> en = ite.next();
			System.out.println(en.getKey() + " .." + en.getValue());
		}
	}
}
public class Demo {
	public static void main(String[] agrs) {
		Map<String, Integer> map = new HashMap<>();
		map.put("李超武", 19);
		map.put("张三", 20);
		for(Map.Entry<String, Integer> en : map.entrySet() )
	}
 }

HashMap存储自定义对象在键位置,怎么保证键唯一

  • 因为是哈希算法,重写hashCode()方法和equals(),哈希值尽量不一样就直接存,一样就调用equals()方法进行比较;写法和HashSet一样;
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result  + age;
	result = prime * result + (this.name == null ? 0 : this.name.hashCode());
	return reult;
}
public boolean equals(Object obj) {
	if(this == obj) {
		return true;
	}
	if(obj == null) {
		return false;
	}
	if(this.getClass != obj.getClass()) {
		return false;
	}
	Student s = (Student)obj;
	if(s.age != this.age) {
		return false;
	}
	if(name == null) {
		return false;
	}else if(!name.equals(s.name)) {
		return false;
	}
	return true;
}

LinekedHashMap

  • 底层也是链表结构,所以保证怎么存就怎么取;使用方法差不多;
public class Demo {
	public static void main(String[] agrs) {
		LinkedHashMap<String, Integer> lhm = new LinekedHashMap<>();
		lhm.put("李超武", 19);
		lhm.put("陈清香", 20);
		for(String key : lhm.keySet()) {
			System.out.println("键 : " + key + " , 值 : " + lhm.get(key));
		}
	}
}

TreeMap

  • 基本和TreeSet一样,也是要么实现Comparable,要么在TreeMap构造中传入Comparator子类对象(比较器),分别重写compareTo()和compare();
public class Demo {
	public static void main(String[] agrs) {
		TreeMap<Student, Integer> tm = new TreeMap<>(new Comparator<Student>() {
			public int compare(Student s1, Student s2) {
				int num = s1.getName().compareTo(s2.getName());
				return num == 0 ? s1.getAge() - s2.getAge() : num;
			}
		});
		tm.put(new Student("a", 10), 100);
		tm.put(new Student("c", 12), 100);
		tm.put(new Student("b", 11), 101);
		for(Student key : tm.keySet()) {
			System.out.println("键:" + key + " = " + tm.get(key));
		}
	}
}

Map集合中嵌套Map集合

public class Demo {
	public static void main(String[] agrs) {
		HashMap<Student, String> hm1 = new HashMap<>();
		hm1.put(new Student("张三",23), "湖南");
		hm1.put(new Student("李四", 24), "湖南");
		HashMap<Stuednt, String> hm2 = new HashMap<>();
		hm2.put(new Student("王五", 25), "上海");
		hm2.put(new Student("赵六", 26), "北京");
		HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
		hm.put(hm1, "一班");
		hm.put(hm2, "二班");
		//遍历
		for(HashMap<Student, String> h : hm.keySet()) {
			String value = hm.get(h);
			for(Student stu : h.keySet()) {
				System.out.println(stu + "=" + h.get(stu) + "=" + value);
			}
		}
	}
}

HashMap与Hashtable的区别

  • 共同点:都是双列集合,底层都是哈希算法;
  • 不同点:HashMap是线程不安全的,效率高的,JDK1.2;Hashtable是线程安全的,效率低,是JDK1.0的;HashMap可以键值可以是null,Hashtable不可以是null;

集合工具类(Collections)

在这里插入图片描述

模拟斗地主发牌、洗牌、并排序

public class Demo {
	public static void main(String[] agrs) {
		String[] name = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
		String[] color = {"黑桃","红桃","梅花","方片"};
		HashMap<Integer, String> hm = new HashMap<>();
		ArrayList<Integer> list = new ArrayList<>();
		int index = 0;
		for(String n : name) {
			for(String c : color) {
				hm.put(index, c.concat(n));
				list.add(index);
				index++;
			}
		}
		hm.put(index, "小王");
		list.add(index);
		index++;
		hm.put(index, "大王");
		//洗牌
		Collections.shuffle(list);
		//发牌并用排序
		TreeSet<Integer> li1 = new TreeSet<>();
		TreeSet<Integer> li2 = new TreeSet<>();
		TreeSet<Integer> li3 = new TreeSet<>(); 
		TreeSet<Integer> dipai = new TreeSet<>();
		for(int i = 0; i < list.size(); i++) {
			if(i >= list.size() - 3) {
				dipai.add(list.get(i));
			}else if(i % 3 == 0) {
				li1.add(list.get(i));
			}else if(i % 3 == 1) {
				li2.add(list.get(i));
			}else {
				li3.add(list.get(i));
			}
		}
		//显示
		print(hm,  li1, "张三");
		print(hm, li2, "李四");
		print(hm, li3, "王五");
		print(hm, dipai, "底牌");
	}
	public static void print(HashMap<Integer,String> hm, TreeSet<Integer> ts, String name) {
			System.out.print("玩家" + name + ": ");
			for(Integer ite : ts) {
				System.out.print(hm.get(ite) + ", ");
			}
			System.out.println();
	}
}

WeakHashMap(弱引用类)

  • 如果假设一个Map中某些内容长时间不使用的话,按照之前的做法是不会删除的,如果希望可以自动删除,可以使用这个类,当里面的某些内容不使用时,可以自动删除
public class Demo_WeakHashMap {
	public static void main(String[] agrs) {
		WeakHashMap<String, String> whm = new WeakHashMap<>();
		whm.put(new String("ss"), new String("sada"));
		whm.put(new String("ddd"), new String("dsf"));
		whm.put("xc", "sad");
		System.gc();  //强制垃圾回收
		System.out.println(whm);
	}
}

IdentityHashMap

  • 键可以重复,比较的是地址值;
    在这里插入图片描述

对象引用强度说明

  • 强引用:当内存不足时,JVM宁可出现OutOfMemeryError错误而使程序停止,也不会回收此对象来释放空间;
  • 软引用:当内存不足时,会回收这些对象的内存,用来实现内存敏感的高速缓存;
  • 弱引用:无论内存是否紧张,被垃圾回收器发现立即回收;
  • 虚引用:和没有任何引用一样;

SortedMap

  • 作用、方法和SortedSet一样;
public class Demo_Sorted {
	public static void main(String[] agrs) {
		SortedMap<String, String> sm = new SortedMap<>();
		sm.put("a", "123");
		sm.put("b", "456");
		sm.put("c", "789");
		System.out.println("第一个Key : " + sm.firstKey());
		System.out.println("对应的值 : " + sm.get(sm.firstKey()));
		System.out.println("最后一个Key : " + sm.lastKey());
		System.out.println("对应的值 : " + sm.get(sm.firstKey()));
		System.out.println("返回指定元素前的集合:");
		for(Map.Entry<String, String> me : sm.headMap("c").entrySet()) {
			System.out.println(me.getKey() + "-->" + me.getValue());
		}
		System.out.println("返回指定元素后的后集合:");
		for(Map.Entry<String,String> me : sm.tailMap("a").entrySet()) {
			System.out.println(me.getKey() + "-->" + me.getValue());
		}
		System.out.println("截取指定元素间的集合 : ");
		for(Map.Entry<String, String> en : sm.subMap("a", "c").entrySet()) {
			System.out.println(en.getKey() + "-->" + en.getValue());
		}
	}
}
  • 方法包含头不包含尾

Stack类

  • 栈是数据结构中比较常见的一种形式,栈是使用典型的先进后出的操作方式完成的;Java中Stack就是栈类;它不是Vector的子类;
  • empty();判断是否空;
  • peek();查看栈顶,但不删除;
  • pop();出栈,同时删除;
  • push(E obj);入栈
  • search(Object obj);在栈中查找;
public class Demo_Stack {
	public static void main(String[] agrs) {
		Stack<String> stack = new Stack<>();
		//入栈
		stack.push("a");
		stack.push("b");
		stack.push("c");
		//出栈
		stack.pop();
		stack.pop();
		stack.pop();
	}
}
  • 了解Stack的使用,了解入栈及出栈操作,以及先进后出的功能;

Properties

  • 属性是在程序中经常出现的一种形式;在类集中专门提拱了一个Properties类,以完成属性的操作;是Hashtable的子类,则也是Map的子类,可以使用Map的全部操作,一般情况下属性类是单独使用的;

  • 写出到xml
    在这里插入图片描述
    在这里插入图片描述

  • 写出到普通文件
    在这里插入图片描述
    在这里插入图片描述

  • 同样还有输入操作分别使用方法load(InputStream)和loadFromXml(InputStream)

一对多的关系

  • 以一个学校有多个学生,一个学生只有一个学校的关系案例
//定义学生类
public class Studnet {
	private String name;
	private int age;
	private School scool; //每个学生只有一个学校
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public void setSchool(School school) {
		this.school = school;
	}
	public School getSchool() {
		return this.school;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return this.name;
	}
	public int getAge() {
		return this.age;
	}
	public String toString() {
		return "姓名 : " + this.name + ", 年龄 : " + this.age;
	}
}
//定义学校类
public class School {
	private String name;
	private List<Student> list;
	public School() {
		list = new ArrayList<Student>();
	}
	public School(String name) {
		this();
		this.name = name;
	}
	public List<Student> getList() {
		return list;
	} 
	public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return this.name;
	}
	public String toString() {
		return "学校: " + this.name;
	}
}
//测试类
public class Test {
	public static void main(String[] agrs) {
		//创建一个学校校
		School school = new School("湖南交通工程学院");
		//创建学生
		Student s1 = new Student("李超武", 19);
		Student s2 = new Student("吴非凡", 19);
		Student s3 = new Student("谢仔晟", 18);
		//学生添加到该学校
		school.getList().add(s1);
		school.getList().add(s2);
		school.getList().add(s3);
		//给学生设置学校
		s1.setSchool(schoool);
		s2.setSchool(schoool);
		s3.setSchool(schoool);
		//迭代输出
		Iterator<Student> iter = school.getList().iterator();
		while(iter.hasNext()) {
			Student stu  = iter.next();
			//学生信息
			System.out.print("-->" + stu);
			//学生所在学校
			System.out.println("-->" + stu.getSchool().getName());
		}
	}
}
  • 总结:明白类类集的关系,那么这种关系将称为日后标准程序的开发基础;1、类的设计;2、类集关系;

多对多的关系

  • 一个学生可以选多门课程,一门课程可以有多名学生参加,那么这就是多对多关系
//定义学生类
public class Student {
	private String name;
	private int age;
	private List<Course> list;
	public Student() {
		list = new ArrayList<>();
	}
	public Student(String name. int age) {
		this();
		this.name = name;
		this.age = age;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getAge() {
		return this.age;
	}
	public String getName() {
		return this.name;
	}
	public List<Course> getAllCourse() {
		return list;
	}
	public String toString() {
		return "姓名 : " + this.name + ", 年龄 : " + this.age;
	}
}
//定义课程类
public class Course {
	private String name;  //课程名称
	private int credit;  //该课程学分
	private list<Student> list; //该课程参加的学生
	public Course() {
		list = new ArrayList<>();
	}
	public Course(String name, int credit) {
		this();
		this.name = name;
		this.credit = credit;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setCredit(int credit) {
		this.credit = credit;
	}
	public int getCredit() {
		return this.credit;
	}
	public String getName() {
		return this.name;
	}
	public List<Student> getAllStudent() {
		return list;
	}
	public String toString() {
		return "课程名称 : " + this.name + ", 课程学分 : " + this.credit;
	}
}
//测试类
public class Test {
	public static void main(String[] sgrs) {
		Course c1 = new Course("C语言", 3);   //定义C语言课程
		Course c2 = new Course("JAVA", 5);   //定义JAVA课程
		//定义三个学生
		Student s1 = new Student("张三" ,19);
		Student s2 = new Student("李四", 20);
		Student s3 = new Student("王五", 21);
		//C语言有三名同学参加
		c1.getAllStudent().add(s1);
		c1.getAllStudent().add(s2);
		c1.getAllStudent().addf(s3);
		//JAVA有两名同学参加
		c2.getAllStudent().add(s2);
		c2.getAllStudent().add(s3);
		//输出C语言的信息,观察有多少同学参加
		System.out.println(c1);
		Iterator<Student> iter1 = c1.getAllStudent().iterator();
		while(iter1.hasNext()) {
			System.out.println("\t--" + iter1.next());
		}
		//输出张三参加了哪些课程
		System.out.println(s1);
		Iterator<Course> iter2 = s1.getAllCourse().iterator();
		while(iter2.hasNext()) {
			System.out.println("\t--" + iter.next());
		}
	}
}
  • 此处多对多关系只是在这种单独类,这样的类可以表示成实体类,只是在这上面设置的关系;

总结

(单列集合)

  • Collection接口中有List和Set两个接口
  • List:存取有序,有索引,可以存重复元素;
  • Set:存取无序,无索引,不可以存重复元素;
  • List有三个实现类:ArrarList、LinkedList、Vector\
  • ArrayList:底层是数组实现的,是线程不安全的;查找修改快,增删慢;
  • LinkedList:底层是链表实现的,是线程不安全的;增删快,查找修改慢;
  • Vector:底层也是数组,线程安全,增删查改都慢;
  • 什么情况使用这些类?
    1、如果删除和增加多,使用LinkedList
    2、如果修改和查找多,使用ArrayList
    3、如果都多使用ArrayList
  • Set有三个实现类:HashSet、LinkedHashSet、TreeSet
  • HashSet:底层是哈希算法实现的,不能保证怎么存怎么取
  • LinkedHashSet:底层是链表实现,也可以保证元素唯一(哈希算法),还保证了存取有序(链表)
  • TreeSet:底层是二叉树实现,可以排序。自定义对象但要实现Comparator\Comparable接口
  • 什么情况使用这些类?
    1、开发不需要对元素进行排序;所以直接用HashSet,效率也高点
    2、TreeSet在面试用得比较多吧
    (双列集合)
    Map接口中有三个实现类:HashMap、LinkedHashMap、TreeMap
    HashMap:底层也是哈希算法,所以特点和HashSet一样,但是算法只针对键有效;
    LinkedHashMap:底层是链表实现,所以特点和LinkedHashSet一样,但数据结构只针对键有效,能保证怎么存怎么取;
    TreeMap:底层是二叉树实现,所以特点和TreeSet一样,但是数据结构也是只针对键有效;
  • 什么时候使用这些类:
    1、开发中用不需要对键排序,所以直接HashMap,效率高;
    2、TreeMap在面试中用得多;

面试题

  1. Collection和Collections的区别?

答:Collection是单列集合顶层接口,Collections是个类是个集合工具类,该类有中有很多操作集合的静态方法;

  1. 说出ArrayList、Vector、LinkedList存储性能和特性

答:ArrayList\Vector都是使用数组方式存储数据,所以对于播入数据和删除数据比较慢,因为涉及数组元素移动等内存操作,数组查找起来比较快,Vector使用synchronized方法(也就是同步,也就是线程安全),性能上比ArrayList差点;LinkedList使用双向链表实现存储,所以插入数据和删除数据比较快,而查找起来比较麻烦,链表或者从头或从尾开始遍历,所以比较慢;

  1. HashMap和Hashtable的区别?
答:HashMap是线程不安全的,Hashtable是线程安全的;HashMap键\值允许存储null,Hashtable不允许;方法上HashMap替换了Hashtable中的contains(),变为containsValue()和containsKey();

上一篇NIO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值