java基础11【异常、集合、迭代器、泛型、Map、断言】

异常
  • 如果在主函数上抛出异常,表示将这个异常抛给了Java虚拟机,JVM默认打印异常的栈轨迹
  • 异常对方法的重载没有影响
  • 在try执行完前,无论出现了异常与否,finally都会执行一次。
  • 在try-catch出现的情况下,JVM在编译的时候认为try不一定能够执行成功,就意味着try中不一定能够正 常返回结果
  • 异常是Java中一套用于问题的反馈和处理的机制
  • Throwable — 异常的顶级父类
  • Error — 错误表示合理(语法上还是逻辑上都是成立的)的应用程序中出现了严重的问题,而且这个问题不应该试图捕获 —意味着在程序中,错误一旦出现不能处理 —
    VirtualMachineError : StackOverflowError, OutOfMemoryError
  • Exception — 表示合理的应用程序想要捕获的问题,也因此可以处理。处理方式:要么捕获要么抛出
  • 编译时异常:在编译时期就已经出现,要求必须处理。
  • CloneNotSupportedException UnsupportedEncodingException ParseException
  • 运行时异常:在编译时期不出现到运行的时候才出现。可以处理可以不处理 — RuntimeException
    ArithmeticException ArrayIndexOutOfBoundsException
    NullPointerException ClassCastException
    StringIndexOutOfBoundsException NumberFormatException
  • 自定义异常:写一个类继承Exception或者是其子类。如果是继承了RuntimeException及其子类,那么这个时候定义的是一个运行时异常;如果继承的是其他的Exception,那么定义的就是编译时异常
  • 异常的捕获方式
    A. 如果多个异常的处理方式各不一样,可以使用多个catch分别捕获分别处理
    B. 如果所有异常的处理方式都一样,可以捕获这些异常的父类进行统一的处理
    C. 如果多个异常进行了分组,那么同一组的异常之间用 | 隔开进行分组处理 — 从JDK1.7开始

目录,再往上一拉

package cn.tedu.exception;

public class ExceptionDemo6 {

	public static void main(String[] args) {
		System.out.println(m());
	}

	public static int m() {

		int i = 4;

		// 方法在栈内存中执行
		// 方法在执行过程中的计算和存储是分成了2块
		// 在代码执行过程中,会出现计算和存储分别进行的现象
		// 代码是从上到下来依次编译运行的
		try {
			// 先运行return i++;
			// 在计算区域将i的值从存储区域取出来进行计算
			// 在计算的时候由于++在后,所以将i的值4作为数据参与下一步运算
			// 下一步运算 return 4;
			// 在执行return 4准备返回的时候需要检查是否有后续操作执行:i的自增,finally
			// 先让i进行自增为5
			// 然后继续执行下一个后续操作是finally
			// 后续操作全部完成最后在执行刚才被挂起的return 4;
			return i++;
		} finally {
			// 在finally中对i再次自增为6
			i++;
			System.out.println("finally:" + i);
		}

	}

}

目录,再往上一拉

public static Person m() {

		Person p = new Person();

		try {
			p.setName("如花");
			p.setAge(80);
			// p是对象,所以return的是p的地址
			return p;
		} finally {
			p.setName("周星星");
			p.setAge(18);
		}

	}

目录,再往上一拉

package cn.tedu.exception;

public class ExceptionDemo2 {

	public static void main(String[] args) /* throws FileNotExistException */ {

		 try {
		 String msg = readTxt("E:\\a.jpg");
		 System.out.println(msg);
		 } catch (FileNotExistException e) {
		 System.out.println(e.getMessage());
		 System.out.println("在处理这个问题~~~");
		 } catch (FileFormatException e) {
		 System.out.println(e.getMessage());
		 } catch (NullPointerException e) {
		 System.out.println("处理空指针~~~");
		 }

		// try {
		// String msg = readTxt("E:\\a.jpg");
		// System.out.println(msg);
		// } catch (Exception e) {
		// System.out.println(e.getMessage());
		// }

		// 一定是先子类异常后父类异常
		try {
			String msg = readTxt("E:\\a.jpg");
			System.out.println(msg);
		} catch (FileNotExistException | FileFormatException e) {
			// System.out.println(e.getMessage());
			// 打印栈轨迹
			e.printStackTrace();
		} catch (NullPointerException e) {
			System.out.println("处理空指针~~~");
		} catch (Exception e) {

		}

		System.out.println("running~~~");
	}

	public static String readTxt(String path) throws FileNotExistException, FileFormatException, NullPointerException {

		if (path == null)
			throw new NullPointerException("亲,路径不能并且空~~~");

		// 可能路径不存在
		if (path.startsWith("H:\\"))
			throw new FileNotExistException("亲,这个文件不存在哦~~~");

		// 文件格式不一样
		if (!path.endsWith(".txt"))
			throw new FileFormatException("亲,需要一个TXT文件~~~");

		return "读取成功~~~";
	}

}

@SuppressWarnings("serial")
class FileFormatException extends Exception {

	public FileFormatException() {
	}

	public FileFormatException(String msg) {
		super(msg);
	}
}

@SuppressWarnings("serial")
class FileNotExistException extends Exception {

	private String msg;

	public FileNotExistException() {
	}

	public FileNotExistException(String msg) {
		this.msg = msg;
	}

	public String getMessage() {
		return msg;
	}
}

目录,再往上一拉

public static void main(String[] args) throws CloneNotSupportedException, ParseException {

		
//		 try {
//			System.out.println(1 / 0);
//		} catch (ArithmeticException e) {
//			System.out.println("在处理这个算术异常~~~");
//		}

		// int[] arr = new int[3];
		// System.out.println(arr[5]);

		// String str = null;
		// System.out.println(str.length());

		// Object o = new Object();
		// String str = (String) o;

//		 Integer in = new Integer("abc");

//		new ExceptionDemo().clone();

//		 "abc".getBytes("abc");

//		 new SimpleDateFormat("yyyy-MM-dd").parse("2012-03-05");

	}
集合
  • 集合是一个存储多个同一类型的数据的容器 — 大小是不固定的
  • - 泛型,表示集合中的元素的数据类型
  • List - 列表
    保证元素的存入顺序,列表中的元素是可以重复的。可以通过下标操作指定位置上的元素
    ArrayList - 顺序表
    底层是基于数组来存储数据。内存空间是连续的。默认初始容量是10,每次扩容默认增加一半,基于了右移。增删操作相对复杂,查询操作相对简单。是一个线程不安全的列表。
    LinkedList - 链表
    基于节点(Node)来实现的。利用节点来存储数据以及维系链表之间每一个节点的关系。内存空间不连续。增删操作相对简单,查询操作相对复杂。是一个线程不安全的列表
    LinkedList:基于节点,内存空间是不连续的。相对增删简单但是查询复杂。是一个线程不安全的列表
    考虑:如果在增删和查询的次数相差不多的情况下,使用ArrayList还是LinkedList? — LinkedList
    因为ArrayList要保证一段连续的存储空间,而LinkedList不用,节点都是散开分布的,所以存储性能好。
    LinkedList的增删是基于二分查询的,跟中间比较,小的话从头开始查找、大的话从尾开始查找。
    在这里插入图片描述
  • Vector - 向量
    最早的列表,依靠数组来存储数据,内存空间一定是连续的,初始默认是10,每次扩容默认增加一倍。是一个线程安全的列表
  • Stack - 栈
    继承了Vector。遵循后进先出/先进后出的原则。最先放入栈中的元素 — 栈底元素,最后放入栈中的元素 — 栈顶元素。将元素放入栈中 — 入栈/压栈,将元素从栈中取出 — 出栈/弹栈
  • Set - 散列集合
    包含的元素不重复,保证元素的唯一性
    HashSet:散列集合,不包含重复的元素,不保证元素的存入顺序。底层基于HashMap来进行数据的存储。 -> 基于了数组+链表结构(链表栈结构)。默认初始容量是16,默认加载因子是0.75f,默认增加一倍。
    TreeSet:要求存入的元素对应的类必须实现Comparable的接口,然后利用接口中compareTo方法进行自然排序;如果需要对某一个TreeSet单独指定排序规则,则需要传入一个Comparator对象
    在这里插入图片描述
  • 加载因子过小,会导致频繁发生rehash操作而降低效率,同时还造成空间资源的浪费
    加载因子过大,会导致每一个桶中的链的长度过长,从而降低增删效率。
    从JDK1.8开始,对HashSet的存储做了调优:如果桶中的链的长度大于了8,会将这个链式结构扭转成一个二叉树结构
  • TreeSet — 会对元素进行整体的自然排序,需要元素对应的类实现Comparable接口
    Comparable —类在实现这个接口之后对这个类的所有的对象进行整体排序
    Comparator — 用于给某个对象单独指定规则
    总结:如果需要给某个TreeSet对象单独指定比较规则,则使用Comparator;如果不指定比较规则,则使用Comparable进行整体的自然排序
  • Collections - 操作集合的工具类

目录,再往上一拉

package cn.tedu.collection;

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo {

	public static void main(String[] args) {

		// 集合中存储的元素类型是String
		Collection<String> c = new ArrayList<String>();

		// 添加元素
		c.add("gwe");
		c.add("hred");
		c.add("hrd");
		c.add("ater");

		// 将集合转化为数组
		
//		 Object[] os = c.toArray();
//		String[] os = (String[]) c.toArray();

//		 for (Object o : os) {
//		 System.out.println(((String) o).length());
//		 }
//		String[] strs = c.toArray(new String[0]);
//		for (String str : strs) {
//			System.out.println(str.length());
//		}

		// 获取集合中的元素个数
		// System.out.println(c.size());

		// 清空集合
		// c.clear();

		// 判断集合是否为空
		// System.out.println(c.isEmpty());

		// 判断元素是否存在
		// System.out.println(c.contains("hrd"));
		// System.out.println(c.contains("aft"));

		// 从集合中移除指定的元素
		// c.remove("gwe");
		// 如果元素不存在,会直接跳过
		// c.remove("age");

//		System.out.println(c);

	}

}

目录,再往上一拉

package cn.tedu.collection;

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

public class ListDemo {

	public static void main(String[] args) {

		List<String> list = new ArrayList<String>();

		// 保证元素的存入顺序
		list.add("bdd");
		list.add("abd");
		list.add("egd");
		list.add("eds");
		list.add("abd");
		list.add(null);

		// 截取子列表
		System.out.println(list.subList(1, 3));

		// 获取指定的元素在列表中第一次出现的位置
		// System.out.println(list.indexOf("abd"));

		// List<String> list2 = new ArrayList<String>();
		// list2.add(new String("bdd"));
		// list2.add("abd");
		// list2.add("egd");
		// list2.add("eds");

		// 比较两个列表的时候是逐位比较是否一致
//		 System.out.println(list.equals(list2));
		// for(int i = 0; i < list.size(); i++)
		// System.out.println(list.get(i));

		// 获取指定下标上的元素
		// System.out.println(list.get(1));

		// 向列表的指定的下标插入指定的元素
		// list.add(1,"fec");
		// list.add(4, "fec");
		// list.add(6, "fec");

		// 移除指定下标上的元素
		// list.remove(0);
		// list.remove(5);

		// 替换指定位置上的元素
		// list.remove(2);
		// list.add(2, "abc");
		// list.set(2, "abc");

		System.out.println(list);

	}

}

右移一位和除二的区别
https://blog.csdn.net/FlushHip/article/details/82495034

目录,再往上一拉

手写ArrayList

package cn.tedu.collection;

import java.util.Arrays;

public class ListExer {

	public static void main(String[] args) {

		ArrList list = new ArrList(1);

		list.add("abc");
		list.add("abc");
		list.add("def");

		// list.add(0, "hijk");

		list.remove(0);

		System.out.println(list);

	}

}

class ArrList {

	private String[] data;

	// 记录元素的个数
	private int size = 0;

	public ArrList() {
		data = new String[10];
	}

	public ArrList(int initialCapacity) {

		if (initialCapacity < 0)
			throw new IllegalArgumentException();

		data = new String[initialCapacity];
	}

	// 添加元素
	public void add(String str) {

		// 判断是否需要扩容
		if (size >= data.length)
			this.grow();

		data[size++] = str;

	}

	// 扩容
	private void grow() {
		if (data.length <= 1)
			data = Arrays.copyOf(data, data.length + 1);
		else
			data = Arrays.copyOf(data, data.length + (data.length >> 1));
	}

	// 插入元素
	public void add(int index, String str) {

		// 判断下标越界
		if (index > size)
			throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);

		// 判断扩容
		if (size >= data.length)
			this.grow();

		// 挪动元素空出对应的位置
		// for (int i = size - 1; i >= index; i--) {
		// data[i + 1] = data[i];
		// }
		System.arraycopy(data, index, data, index + 1, size - index);
		// // 插入元素
		data[index] = str;

		size++;
	}

	private void out(int index) {
		// 判断下标越界
		if (index >= size)
			throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);

	}

	// 根据下标移除指定的元素
	public void remove(int index) {

		this.out(index);

		// for(int i = index; i < size - 1; i++){
		// data[i] = data[i + 1];
		// }
		System.arraycopy(data, index + 1, data, index, size - (index + 1));

		size--;

	}

	// 移除指定的元素
	public void remove(String str) {

		// 首先先找到这个元素出现的位置
		int index = indexOf(str);

		if (index != -1)
			this.remove(index);

	}

	// 找这个元素第一次出现的位置
	public int indexOf(String str) {

		for (int i = 0; i < size; i++) {

			if (data[i] == str || data[i] != null && data[i].equals(str))
				return i;
		}

		return -1;

	}

	public void clear() {
		data = new String[10];
		size = 0;
	}

	public boolean contains(String str) {
		return indexOf(str) != -1;
	}

	public String get(int index) {

		this.out(index);

		return data[index];
	}

	public boolean isEmpty() {
		return size == 0;
	}

	public void set(int index, String str) {

		this.out(index);

		data[index] = str;

	}

	public int size() {
		return size;
	}

	@Override
	public String toString() {

		StringBuilder sb = new StringBuilder("[");

		for (int i = 0; i < size; i++) {
			sb.append(data[i]).append(", ");
		}

		String str = sb.toString();

		if (size > 0)
			str = str.substring(0, str.length() - 2);

		return str += "]";

	}
}

手写LinkedList
目录,再往上一拉

package cn.tedu.collection;

public class ListExer2 {

	public static void main(String[] args) {

		LinkList list = new LinkList();

		list.add("a");
		list.add("b");
		list.add("c");

		// list.add(0,"d");
		// list.add(1, "e");

		// list.remove(0);
		// list.remove(2);
		list.remove(1);

		System.out.println(list);

	}

}

class LinkList {

	private int size = 0; // 节点个数
	private Node first; // 第一个节点
	private Node last; // 最后一个节点  

	public LinkList() {
	}

	public void add(String str) {

		// 创建节点存储数据
		Node node = new Node(null, str, null);

		// 列表此时为空
		if (size == 0) {
			// 如果列表为空,则头结点指向新节点
			this.first = node;
		} else {
			// 原来的尾节点的下一位置为新节点
			this.last.next = node;
			// 新节点的上一位是原来的尾节点
			   = this.last;
		}
		// 新的节点变成了尾节点
		this.last = node;
		size++;
	}

	public void add(int index, String str) {

		// 判断下标是否越界
		if (index > size)
			throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);

		// 在尾部追加
		if (index == size) {
			this.add(str);
			return;
		}

		Node node = new Node(null, str, null);
		// 插入的头部
		if (index == 0) {
			node.next = this.first;
			this.first.prev = node;
			this.first = node;
		} else {

			Node no = this.getNode(index);

			// 原节点的上一个节点的下一位变成新的节点
			no.prev.next = node;
			// 新的节点的上一位是原节点的上一位
			node.prev = no.prev;
			// 新节点的下一位是原来的节点
			node.next = no;
			// 原节点的上一位是新的节点
			no.prev = node;

		}
		size++;

	}

	private Node getNode(int index) {
		// 获取指定位置的节点
		Node no = this.first;
		for (int i = 0; i < index; i++) {
			no = no.next;
		}
		return no;
	}

	private void out(int index) {
		// 判断下标越界
		if (index >= size)
			throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);

	}

	public void remove(int index) {

		this.out(index);

		// 头部
		if (index == 0) {
			this.first = this.first.next;
			this.first.prev = null;
		} /* 尾部 */ else if (index == size - 1) {
			this.last = this.last.prev;
			this.last.next = null;
		} else {
			Node node = this.getNode(index);

			// 原节点的上一个节点的下一位变成原节点的下一位
			node.prev.next = node.next;
			// 原节点的下一个节点的上一位变成原节点的上一位
			node.next.prev = node.prev;
		}
		size--;
	}

	public int indexOf(String str) {

		Node node = this.first;
		for (int i = 0; i < size; i++) {
			String data = node.data;
			if (data == str || data != null && data.equals(str))
				return i;

			node = node.next;

		}

		return -1;

	}

	public String toString() {

		StringBuilder sb = new StringBuilder("[");
		Node node = this.first;
		for (int i = 0; i < size; i++) {
			sb.append(node.data).append(", ");
			node = node.next;
		}

		String str = sb.toString();
		if (size > 0)
			str = str.substring(0, str.length() - 2);

		return str += "]";
	}

	// 利用节点存储数据
	private class Node {

		Node prev; // 上一个节点
		String data; // 元素
		Node next; // 下一个节点

		public Node(Node prev, String data, Node next) {
			super();
			this.prev = prev;
			this.data = data;
			this.next = next;
		}

	}

}
set集合排序

目录,再往上一拉

package cn.tedu.collection;

import java.util.Comparator;
import java.util.TreeSet;

public class SetDemo2 {

	public static void main(String[] args) {

		// TreeSet<String> set = new TreeSet<String>();

		// 会根据自然顺序(往往是升序)进行排序
		// set.add("d");
		// set.add("g");
		// set.add("a");
		// set.add("r");
		// set.add("c");

		// System.out.println(set);

		TreeSet<Student> set = new TreeSet<Student>();
//		 按照分数进行降序排序
//		 TreeSet<Student> set = new TreeSet<Student>(new Comparator<Student>()
//		 {
//		
//		 @Override
//		 public int compare(Student o1, Student o2) {
//		 return o2.getScore() - o1.getScore();
//		 }
//		 });

		// 要求set中的元素所对应的类必须实现Comparable
		set.add(new Student("01金毛狮王", 20, 59));
		set.add(new Student("03白眉鹰王", 50, 18));
		set.add(new Student("02紫衫龙王", 49, 89));
		set.add(new Student("05青翼蝠王", 38, 60));

		for (Student s : set) {
			System.out.println(s);
		}

	}

}

class Student implements Comparable<Student> {

	private String name;
	private int age;
	private int score;

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

	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;
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}

	@Override
	// 排序规则就写在compareTo中
	// 在排序的时候会根据返回值的正负来确定元素的排序顺序
	// 如果返回了一个正数,那么this就会排在o之后
	// 如果返回了一个负数,那么this就会排在o之前
	public int compareTo(Student o) {
//		return this.age - o.age;  //升序
//		return o.age - this.age; //降序
		return name.compareTo(o.name);
	}

}

Stack - 栈集合
目录,再往上一拉

Stack<String> s = new Stack<String>();

		// 添加元素
		s.push("d");
		s.push("a");
		s.push("e");
		s.push("s");
		s.push("h");
		
		// 从栈顶到栈底依次查找,以1基数
		System.out.println(s.search("a"));
		
		// 判断栈是否为空
		// System.out.println(s.empty());

		// 查看栈顶元素
		// 如果栈为空,则抛出空栈异常
		// System.out.println(s.peek());

		// 移除栈顶元素
		// System.out.println(s.pop());

		System.out.println(s);

练习:使用数组/节点(Node)完成一个Stack — empty peek pop push search
目录,再往上一拉

package cn.tedu.collection;

import java.util.Arrays;
import java.util.EmptyStackException;

public class StackExer {
	
public static void main(String[] args) {
//	ArrStack as = new ArrStack();
//	as.push("a");
//	as.push("b");
//	as.push("c");
//	as.pop();
	
	LinkStack ls = new LinkStack();
	
	ls.push("a");
	ls.push("b");
	ls.push("c");
	
	System.out.println(ls);

}
}

class LinkStack {

	private int size = 0;
	private Node first;

	public boolean empty() {
		return size == 0;
	}

	public void push(String str) {

		Node node = new Node(null, str);

//		if (size != 0) { 
//			node.next = this.first;
//		}
		
		this.first = node;
		size++;

	}

	public String peek() {
		if (size == 0)
			throw new EmptyStackException();

		return this.first.data;
	}

	public String pop() { 
		String str = this.peek();
		this.first = this.first.next;
		size--;
		return str;
	}

	public int search(String str) {

		Node node = this.first;
		for (int i = 0; i < size; i++) {

			if (node.data == str || str != null && str.equals(node.data))
				return i + 1;

			node = node.next;

		}

		return -1;

	}
	
	

	@Override
	public String toString() {
		return "LinkStack [size=" + size + ", first=" + first + "]";
	}



	private class Node {

		Node next;
		String data;

		public Node(Node next, String data) {
			super();
			this.next = next;
			this.data = data;
		}

	}

}

class ArrStack {

	private String[] data = new String[10];
	private int size = 0;
	
	public String peek() {
		// 判断栈中是否有元素
		if (size == 0)
			throw new EmptyStackException();

		return data[size - 1];
	}

	public String pop() {

		String str = this.peek();
		size--;
		return str;

	}

	public void push(String str) {

		// 判断是否需要扩容
		if (size >= data.length)
			data = Arrays.copyOf(data, data.length * 2);

		data[size++] = str;

	}

	public int search(String str) {

		// for(int i = size - 1, j = 1; i >= 0; i--, j++){
		//
		// if(str == data[i] || str != null && str.equals(data[i]))
		// return j;
		//
		// }
		for (int i = size - 1; i >= 0; i--) {

			if (str == data[i] || str != null && str.equals(data[i]))
				return size - i;

		}

		return -1;

	}

}

JDK8 新特性
目录,再往上一拉

package exer1;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class StreamDemo {

	public static void main(String[] args) {

		List<String> list = new ArrayList<String>();

		list.add("abe");
		list.add("egs");
		list.add("dgse");
		list.add("3sdf");
		list.add("sdh8");
		list.add("dbks");
		list.add("vn3hdso");

		// 流式结构,但不是流,可以批量的操作集合中的数据
		// JDK1.8的新特性之一
		Stream<String> stream = list.stream();
		 System.out.println(stream.allMatch(str -> str.matches(".*\\d.*")));

		// 判断集合中是否包含以字母a开头的字符串
		System.out.println(stream.anyMatch(str -> str.startsWith("a")));
		 stream.filter(new Predicate<String>() {
		
		 @Override
		 public boolean test(String t) {
		 return t.matches(".*\\d.*");
		 }
		 }).forEach(new Consumer<String>() {
		
		 @Override
		 public void accept(String t) {
		 System.out.println(t);
		 }
		 });
		 stream.filter(str -> str.matches(".*\\d.*"))
		 .map(str -> str.replaceAll("\\d", ""))
		 .forEach(str -> System.out.println(str));

		// for (String str : list) {
		// if (str.matches(".*\\d.*")) {
		// str = str.replaceAll("\\d", "");
		// System.out.println(str);
		// }
		// }

	}

}

Vector
目录,再往上一拉

package cn.tedu.collection;

import java.util.Enumeration;
import java.util.Vector;

public class VectorDemo {

	public static void main(String[] args) {

		// Vector<String> v = new Vector<String>();
		// 表示向量的初始容量是10,每次扩容增加5个
		// Vector<String> v = new Vector<String>(10, 5);
		// System.out.println(v.capacity());
		//
		// for (int i = 0; i < 21; i++) {
		// v.add("a");
		// }
		//
		// System.out.println(v.capacity());

		Vector<String> v = new Vector<String>();

		v.add("a");
		v.add("d");
		v.add("t");
		v.add("h");

		// 获取迭代器
		Enumeration<String> e = v.elements();

		// 判断后续是否还有元素
		while (e.hasMoreElements()) {

			// 挪动指针获取这一个元素
			String str = e.nextElement();
			System.out.println(str);

			// 无法清空集合
			// v.remove(str);
		}

		System.out.println(v);
	}

}

迭代器

目录,再往上一拉

  • 迭代器是通过指针的挪动来依次获取集合中的每一个元素。
  • Enumeration - 最早期的迭代器
  • Iterator -通过迭代器自带的remove方法来移除当前在迭代的元素, it.remove();
    实质是:一个集合实现迭代器后(产生一个迭代器对象),迭代器会复制一份集合,然后对这份集合中每一个元素进行标记(true/false),然后去和原集合对比,确定每一个元素是否该删除。因此在迭代过程中不允许直接增删原集合,否则会产生ConcurrentModificationException 当前认证(标记)异常。
  • Collection中的iterator方法是从Iterable中继承过来的,实现了Iterable接口的类产生的对象可以被增强for循环进行遍历。 — 增强for循环也是JDK1.5的特性之一。增强for循环本质上是一个迭代遍历,简化了迭代操作!
  • 迭代器:Iterator - 通过状态标记和指针的挪动来遍历元素 - 在迭代过程中不允许直接增删原集合。Iterable接口提供了获取迭代器的方法,实现了这个接口的类所产生的对象可以被增强for循环遍历
List<String> list = new ArrayList<String>();

		list.add("abe");
		list.add("egs");
		list.add("dgse");
		list.add("dase");
		list.add("3sdf");
		list.add("sdh8");
		list.add("dbks");
		list.add("vn3hdso");
		
		// 通过iterator方法获取到一个Iterator对象
		Iterator<String> it = list.iterator();
		
		// 判断是否有下一个元素
		while(it.hasNext()){
			
			// 挪动指针获取这个元素
			String str = it.next();
			System.out.println(str);
			
			// 通过迭代器自带的remove方法来移除当前在迭代的元素
			// it.remove();
			list.remove(str);
		}
		
		System.out.println(list);

目录,再往上一拉

泛型

参数化类型 - ParameterizedType — JDK1.5的特性之一
用具体类型来替代泛型的过程 — 泛型的擦除 — 编译期
? extends 类/接口 表示传入这个类/接口或者是其子类/子接口对象 — 上限
? super 类/接口 表示传入这个类/接口及其父类/父接口的对象 — 下限
? 表示泛型的通配符

package cn.tedu.type;

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

public class TypeDemo1 {

	public static void main(String[] args) {

		// 在早期没有泛型的限制的时候,集合中存储元素是Object类型
		// List list = new ArrayList();
		// List<String> list = new ArrayList();
		// List list = new ArrayList<String>();
		// List<String> list = new ArrayList<String>();
		// 从JDK1.7开始,后边实现类的泛型可以省略不写
		// 会根据程序的上文来进行类型的自动推导
		List<String> list = new ArrayList<>();

		list.add("a");
		// list.add(5);
		// list.add(3.5);
		// list.add(new Object());

		// Iterator it = list.iterator();
		// while (it.hasNext()) {
		// Object o = it.next();
		//
		// if (o instanceof String) {
		// String str = (String) o;
		// } else if (o instanceof Integer) {
		// Integer in = (Integer) o;
		// }
		// }

	}

	// public static void m(List list){}

}

目录,再往上一拉

package cn.tedu.type;

public class TypeDemo2 {

	public static void main(String[] args) {

		Demo<String, Integer> demo = new Demo<>();
		demo.set("abc");
		System.out.println(demo.get());
	}

}

// <T> 表示定义了一个泛型叫T
// 泛型的命名只要符合标识符的命名规则即可
// 习惯上泛型一般只使用一个大写字母进行命名
// T type
// E element
// K key
// V value
// R result/return
class Demo<T, E> {

	// 泛型定义的变量不能直接实例化
	private T t;
	E e;

	public void set(T t) {
		this.t = t;
	}

	public T get() {
		return t;
	}

}

目录,再往上一拉

package cn.tedu.type;

public class TypeDemo3 {

	public static void main(String[] args) {

		A a = new A();
		a.m(5);
		a.m(true);
		a.m("def");

	}

}

class A {

	// 表示给当前的方法定义了一个单独的泛型
	public <T> void m(T t) {
		System.out.println(t.getClass());
	}

}

目录,再往上一拉

package cn.tedu.type;

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

public class TypeDemo4 {

	public static void main(String[] args) {

		List<Integer> ins = new ArrayList<>();
		ins.add(3);
		ins.add(4);
		ins.add(6);
		ins.add(7);
		ins.add(0);
		List<Double> dos = new ArrayList<>();
		dos.add(3.6);
		dos.add(4.2);
		dos.add(6.8);
		dos.add(7.7);
		dos.add(0.2);

		// 泛型不存在向下兼容
		print(ins);
		print(dos);

		// List<String> strs = new ArrayList<>();
		// print(strs);

	}

	// 写一个新的方法来遍历元素类型是数字的列表
	// 元素类型是Number或者是其子类
	// ? extends 类/接口 表示传入这个类/接口或者是其子类/子接口对象
	// 所能传入的元素的最大类型限定为Number
	// 规定了泛型的上限
	public static void print(List<? extends Number> list) {

		// 不能再添加任何元素除非是null
		list.add(null);
		
		for (Number n : list) {
			System.out.println(n);
		}

	}
	
	// 泛型的下限
	// 传入元素类型是String及其父类的列表
	// ? super 类/接口 表示传入这个类/接口及其父类/父接口的对象
	// 表示传入的最小类型是String
	public static void m(List<? super String> list){
		
		list.add("abc");
		for (Object o : list) {
			System.out.println(o);
		}
		
	}

}

目录,再往上一拉

package cn.tedu.type;

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

public class TypeDemo5 {
	
	public static void main(String[] args) {
		
		List<Integer> ins = new ArrayList<>();
		ins.add(7);
		ins.add(3);
		ins.add(6);
		ins.add(0);
		ins.add(4);
		
		sort(ins);
	}
	
	// 可以接收任意类型,但是在排序(操作)期间不允许发生增删操作
	public static void sort(List<?> list){
		
		list.add(null);
		
	}

}

Map<K, V> - 映射

目录,再往上一拉

  • 映射:用于存储键值对的容器。每一个键对应一个值,键是唯一的。
  • 一个键对应一个值。键是唯一的,值可以重复。
  • 每一个键和它所对应的值构成了键值对。— 一个Map是由多个键值对来组成。
  • 将每一个键值对看作一个对象,抽取出来一个代表键值对的接口
  • Entry,内部会有一个内部类实现这个Entry接口。Entry是Map中的内部接口 — 一个Map是由多个Entry对象来组成的
  • Map不是集合,但是Map是Java集合框架的成员。
    Java集合框架(Java Collections Framework)包含:集合、数组、映射以及操作它们的工具类 — Arrays、Collections、Interator、Comparable、Comparator
  • 遍历映射
    方式一:先获取映射中所有的键组成的集合,然后通过键获取对应的值
    方式二:将所有的键值对放入集合中,然后遍历集合获取这个键值对的数据
  • HashMap:基于哈希码存储,然后允许键和值为null。默认初始容量是16,默认加载因子是0.75f,每次默认增加一倍。自定义初始容量x,这个x介于[2n,2n+1],那么初始容量一定是2n+1 — 底层保证HashMap的容量永远是2n的形式。本身是一个异步式线程不安全的映射
  • Hashtable:基于哈希码存储,然后不允许键和值为null。默认初始容量是11,默认加载因子是0.75f,每次默认增加一倍,然后再+1 — 11 -> 23。本身是一个同步式线程安全的映射。 ConcurrentHashMap — 异步式线程安全的映射
Map<String, Integer> map = new HashMap<>();

		// 添加元素
		map.put("d", 4);
		map.put("h", 7);
		map.put("z", 7);
		map.put("o", 3);
		map.put("t", 3);
		// 如果键相同则对应的值覆盖
		map.put("o", 0);
		map.put("e", null);

		// 获取键值对的个数
		System.out.println(map.size());

		// 移除键值对
//		 map.remove("o");

		// 判断键是否存在
		// System.out.println(map.containsKey("f"));
		// 判断值是否存在
		// System.out.println(map.containsValue(4));

		// 根据指定的键获取对应的值
//		 System.out.println(map.get("o"));
		// 如果键不存在则返回null
		// System.out.println(map.get("y"));Map<String, Integer> map = new HashMap<>();
		map.put("d", 4);
		map.put("h", 7);
		map.put("z", 7);
		map.put("o", 3);
		map.put("t", 3);

		// 遍历映射
		// 方式一:先获取映射中所有的键组成的集合,然后通过键获取对应的值
		// keySet表示将映射中的所有的键放入一个Set集合中
		// Set<String> set = map.keySet();
		// for (String key : set) {
		// System.out.println(key + "=" + map.get(key));
		// }

		// 方式二:将所有的键值对放入集合中,然后遍历集合获取这个键值对的数据
		// entrySet表示将映射中的所有的键值对放入一个Set集合中
		Set<Map.Entry<String, Integer>> set = map.entrySet();
		// 遍历集合,然后从键值对中获取键和值
		for (Map.Entry<String, Integer> entry : set) {
			System.out.println(entry.getKey() + "=" + entry.getValue());
		}
		

		System.out.println(map);

输入一个字符串,统计其中每一个字符出现的次数
目录,再往上一拉

package cn.tedu.map;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * 输入一个字符串,统计其中每一个字符出现的次数
 */
public class MapExer {

	@SuppressWarnings("resource")
	public static void main(String[] args) {

		// 获取字符串
		Scanner s = new Scanner(System.in);
		String str = s.next();

		// 定义一个映射,键存储字符,值存储个数
		Map<Character, Integer> map = new HashMap<>();

		// 遍历字符串,然后统计每一个字符出现的次数
		for (int i = 0; i < str.length(); i++) {
			// 获取对应位置的字符
			char c = str.charAt(i);
			// 判断这个字符在映射是否出现过
			if (map.containsKey(c))
				map.put(c, map.get(c) + 1);
			else
				map.put(c, 1);
		}
		// 遍历映射
		for (Map.Entry<Character, Integer> entry : map.entrySet())
			System.out.println(entry.getKey() + ":" + entry.getValue());

	}

    }

目录,再往上一拉

断言
  • 对结果进行预测。
  • assert 断言条件 : 错误信息;
  • 在Java中,断言不是默认开启的,需要利用参数手动指定开启 -> -ea -> -enableassertion
Scanner s = new Scanner(System.in);

		int age = s.nextInt();

		// 进行断言
		// 如果断言成功,则继续往下执行
		// 如果断言失败,则抛出错误AssertionError
		assert age > 0 : "预测年龄应该是大于0的数值,实际上是" + age;
		
		System.out.println(age);

		Scanner s = new Scanner(System.in);

		int age = s.nextInt();

		// 进行断言
		// 如果断言成功,则继续往下执行
		// 如果断言失败,则抛出错误AssertionError
		assert age > 0;
		
		System.out.println(age);

扩展:native修饰方法— 本地方法,没有方法体但不是抽象方法,方法体是在JVM中用C语言完成的,在本地方法栈中执行
目录,再往上一拉

Scanner s = new Scanner(System.in);

		// 用空白字符进行分隔
		 int i = s.nextInt();
		 double d = s.nextDouble();
		 String str = s.next();
		// 用回车换行进行分隔
		// 以上次结束作为本次的开始
		String str2 = s.nextLine();

		// System.out.println(i);
		// System.out.println(d);
		// System.out.println(str);
		System.out.println(str2.equals(""));
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值