javaSE(七)

版权声明:博主原创,转发请私信。 https://blog.csdn.net/YooFale/article/details/82928234

1.对象数组

类的有参构造构造出对象,将对象存储在数组中。

案例代码:

Student[] arr = new Student[5];
		arr[0] = new Student("张一", 11);
		arr[1] = new Student("张二", 12);
		arr[2] = new Student("张三", 13);
		arr[3] = new Student("张四", 14);
		arr[4] = new Student("张五", 15);
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}

对应的内存图:

2.集合体系

数组和集合的区别
    * 区别1 : 
        * 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
        * 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象

    * 区别2:
        * 数组长度是固定的,不能自动增长
        * 集合的长度的是可变的,可以根据元素的增加而增长

因为JDK1.0Vector就出现了,JDK1.2才出现Collection,所以命名不符合新的命名规则。
 

3.Collection集合的基本功能

案例代码:

@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
public class Demo2_Collection {
	/**
	 * boolean add(E e)
	 * boolean remove(Object o)
	 * void clear()
	 * boolean contains(Object o)
	 * boolean isEmpty()
	 * int size()
	 * 注意:要了解详细信息,请使用 -Xlint:unchecked重新编译.
	 * add方法如果是List集合一直都返回true,因为List集合中是可以存储重复元素的
	 * 如果是Set集合当存储重复元素的时候,就会返回false
	 * ArrayList的父类的父类重写toString方法,所以在打印对象的引用的时候,输出的结果不是Object类中toString的结果
	 */
	public static void main(String[] args) {
		// 接口不能具体实现类,只能父类引用指向子类对象
		Collection c = new ArrayList();
		boolean add = c.add("a");
		boolean add2 = c.add(true);
		boolean add3 = c.add(100);
		boolean add4 = c.add("abc");
		boolean add5 = c.add(new Student("张三", 23));
		System.out.println(c);
		c.remove("trueaaaa");
		System.out.println(c);
		System.out.println(c.contains(true));
		System.out.println(c.isEmpty());
		System.out.println(c.size());
		c.clear();
		System.out.println(c.size());
	}

需要说明的问题有:

remove不存在的内容,并不会报错

创建实例必须使用父类引用指向子类对象

在这里没有使用泛型会出现黄色波浪线,可以cmd+1将这个标注在方法上,将其上移至类上,适用于类中所有方法。

4.集合遍历

案例代码:

public static void demo2() {
		Collection c = new ArrayList();
		c.add(new Student("张三", 18));
		c.add(new Student("李四", 19));
		c.add(new Student("王五", 21));
		c.add(new Student("刘流", 34));
		Object[] array = c.toArray();
		for (int i = 0; i < c.size(); i++) {
			// System.out.println(array[i]);
			Student s = (Student) array[i];
			System.out.println(s.getName() + "..." + s.getAge());
		}
	}

	public static void demo1() {
		Collection c = new ArrayList();
		c.add("a");
		c.add("b");
		c.add("c");
		Object[] array = c.toArray();
		for (int i = 0; i < array.length; i++) {
			System.out.println(array[i]);
		}
	}

集合遍历需要先调用toArray方法,将集合转成数组,再来实现数组的遍历。

遍历的时候,数组中的数据类型是Object,多态的弊端:无法直接调用子类特有的方法,所以,如果集合中是对象,但是想调用对象的方法,需要向下强制转型成具体的类。

5.Collection类带All的功能

案例代码:

public static void main(String[] args) {
		//demo1();
		//demo2();
		//demo3();
		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");
		c2.add("e");
		c2.add("f");
		
		//取交集,如果调用的集合改变就返回true,如果调用的集合不变就返回false
		boolean b = c1.retainAll(c2);					//取交集
		System.out.println(b);
		System.out.println(c1);
	}

	public static void demo3() {
		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("z");
		
		boolean b = c1.containsAll(c2);				//判断调用的集合是否包含传入的集合
		System.out.println(b);
	}

	public static void demo2() {
		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("z");
		
		boolean b = c1.removeAll(c2);					//删除的是交集
		System.out.println(b);
		System.out.println(c1);
	}

	public static void demo1() {
		Collection c1 = new ArrayList();
		c1.add("a");
		c1.add("b");
		c1.add("c");
		c1.add("d");
		
		Collection c2 = new ArrayList();			//alt + shift + r改名
		c2.add("a");
		c2.add("b");
		c2.add("c");
		c2.add("d");
		
		//c1.addAll(c2);							//将c2中的每一个元素添加到c1中
		c1.add(c2);									//将c2看成一个对象添加到c1中
		System.out.println(c1);
	}

说明:

        addAll是添加集合的元素,add是添加集合本身

        removeAll是删除交集

        containsAll判断调用的集合是否包含参数集合

        retainAll是留下交集,此处需要注意,如果参数集合大于等于调用集合,那么调用集合不变,返回false,如果参数集合小于调用集合,调用集合发生变化,返回true。

6.迭代器

案例代码:

public static void main(String[] args) {
		Collection c = new ArrayList();
		c.add(new Student("张三", 18));
		c.add(new Student("李四", 19));
		c.add(new Student("王五", 21));
		c.add(new Student("刘流", 34));
		Iterator iterator = c.iterator();
		while (iterator.hasNext()) {
			// System.out.println(iterator.next());
			Student s = (Student) iterator.next();
			System.out.println(s.getName() + "..." + s.getAge());
		}
	}

底层实现:

Itr类,cursor是指针,调用一次next方法,cursor会加一。hasnext判定标准是cursor != size,当cursor等于size的时候,已经遍历完毕,自然没有next,所以是false。

7.List集合特有的功能

案例代码:

	public static void demo4() {
		ArrayList list = new ArrayList();
		list.add("a");
		list.add("b");
		list.add("c");
		System.out.println(list);
		// 返回的值是替换出来的对应索引的值
		Object set = list.set(0, 1);
		System.out.println(set);
		System.out.println(list);
	}

	public static void demo3() {
		ArrayList list = new ArrayList();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		// Iterator iterator = list.iterator();
		// while (iterator.hasNext()) {
		// System.out.println(iterator.next());
		// }
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
	}

	public static void demo2() {
		ArrayList list = new ArrayList();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add("厉害啊");
		// 默认是索引
		Object remove = list.remove(1);
		// remove的是object,返回的是boolean,remove的是index,返回的是object
		System.out.println(remove);
		System.out.println(list);
		list.remove("厉害啊");
		System.out.println(list);
	}

	public static void demo1() {
		ArrayList list = new ArrayList();
		list.add("a");
		list.add("b");
		System.out.println(list);
		list.add(2, "c");
		System.out.println(list);
	}

          void add(int index,E element)
          E remove(int index)
          E get(int index)
          E set(int index,E element)

add方法,需要注意索引值只能小于等于list集合的长度,不然会报索引越界。

remove方法,如果参数列表中是索引,那么返回值是对应索引位置的值,如果参数列表中是object,返回的是布尔类型。

get方法,获取的是对应索引的object,可用于遍历,arrayList也可以使用迭代器进行遍历。

set方法,返回值是被以前索引对应的值。

8.并发修改异常

@SuppressWarnings({ "rawtypes", "unchecked" })
public class Demo3_List {
	/**
	 ** A:案例演示
	 * 需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
	 */
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("a");
		list.add("b");
		list.add("world");
		list.add("c");
		list.add("e");
		// demo1(list);
		ListIterator iterator = list.listIterator();
		while (iterator.hasNext()) {
			if ("world".equals((String) iterator.next())) {
				iterator.add("javaee");
			}
		}
		System.out.println(list);
	}

	public static void demo1(List list) {
		Iterator iterator = list.iterator();
		while (iterator.hasNext()) {
			String s = (String) iterator.next();
			if ("world".equals(s)) {
				list.add("javaee");
			}
		}
	}

}

调用集合的add方法在遍历的同时进行修改操作,会报出如下错误:

Exception in thread "main" java.util.ConcurrentModificationException

说明:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

此时list的add方法不能进行操作,所以需要使用List类特有的迭代器ListIterator中的add方法进行操作。

案例代码:

@SuppressWarnings({ "rawtypes", "unchecked" })
public class Demo4_ListIterator {

	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("a");
		list.add("b");
		list.add("world");
		list.add("c");
		list.add("e");
		ListIterator iterator = list.listIterator();
		while (iterator.hasNext()) {
			System.out.print(iterator.next());
		}
		System.out.println("");
		while (iterator.hasPrevious()) {
			System.out.print(iterator.previous());
		}
	}

}

ListIterator还有从后向前遍历的方法,不过需要在从前往后以后才可以,因为索引的位置需要先到最后面,才能倒着遍历。

9.Vector类

需要了解的方法:

addElement()

elements()     返回值属于Enumeration

Enumeration的方法,需要了解hasMoreElements()和nextElemennt()

案例代码:

@SuppressWarnings({ "unchecked", "rawtypes" })
public class Demo5_Vector {

	public static void main(String[] args) {
		Vector v = new Vector();
		v.addElement("a");
		v.addElement("b");
		v.addElement("c");
		v.addElement("d");
		// 获取枚举
		Enumeration elements = v.elements();
		while (elements.hasMoreElements()) {
			Object element = elements.nextElement();
			System.out.println(element);
		}
	}

}

在多个字节流拼接成序列字节流的时候会使用

10.List子类的特点及选择

数组有序,

Vector和ArrayList的区别

     Vector线程安全,效率低(但是ArrayList同样可以达到线程安全的效果,所以Vector被放弃了)

     ArrayList线程不安全,效率高。 

     他们都是数组实现的

ArrayList和LinkedList的区别

     ArrayList底层是数组,查询修改快,增加删除慢

     LinkedList底层是链表,查询修改慢,增加删除块

     他们都是线程不安全的

List有三个子类,一般选择哪个?

     查询和修改多用ArrayList

     增加和删除多用LinkedList

     都多,建议使用ArrayList

     Vector已经放弃了

11.去除List中的重复元素

案例代码:

public static void main(String[] args) {
		ArrayList list = new ArrayList();
		list.add("a");
		list.add("a");
		list.add("b");
		list.add("b");
		list.add("c");
		list.add("c");
		list.add("c");
		list.add("c");
		
		ArrayList newList = getSingle(list);
		System.out.println(newList);
	}

	/*
	 * 创建新集合将重复元素去掉
	 * 1,明确返回值类型,返回ArrayList
	 * 2,明确参数列表ArrayList
	 * 
	 * 分析:
	 * 1,创建新集合
	 * 2,根据传入的集合(老集合)获取迭代器
	 * 3,遍历老集合
	 * 4,通过新集合判断是否包含老集合中的元素,如果包含就不添加,如果不包含就添加
	 */
	public static ArrayList getSingle(ArrayList list) {
		ArrayList newList = new ArrayList<>();					//1,创建新集合
		Iterator it = list.iterator();							//2,根据传入的集合(老集合)获取迭代器
		
		while(it.hasNext()) {									//3,遍历老集合
			Object obj = it.next();								//记录住每一个元素
			if(!newList.contains(obj)) {						//如果新集合中不包含老集合中的元素
				newList.add(obj);								//将该元素添加
			}
		}
		
		return newList;
	}

用新的List来装老List里面的东西,有就不装,没有就装。

去掉List中重合的自定义对象:

public static void main(String[] args) {
		ArrayList list = new ArrayList();				//创建集合对象
		list.add(new Person("张三", 23));
		list.add(new Person("张三", 23));
		list.add(new Person("李四", 24));
		list.add(new Person("李四", 24));
		list.add(new Person("李四", 24));
		list.add(new Person("李四", 24));
		
		//ArrayList newList = getSingle(list);			//调用方法去除重复
		//System.out.println(newList);
		list.remove(new Person("张三", 23));
		System.out.println(list);
	}

	/*
	 * 创建新集合将重复元素去掉
	 * 1,明确返回值类型,返回ArrayList
	 * 2,明确参数列表ArrayList
	 * 
	 * 分析:
	 * 1,创建新集合
	 * 2,根据传入的集合(老集合)获取迭代器
	 * 3,遍历老集合
	 * 4,通过新集合判断是否包含老集合中的元素,如果包含就不添加,如果不包含就添加
	 */
	public static ArrayList getSingle(ArrayList list) {
		ArrayList newList = new ArrayList<>();					//1,创建新集合
		Iterator it = list.iterator();							//2,根据传入的集合(老集合)获取迭代器
		
		while(it.hasNext()) {									//3,遍历老集合
			Object obj = it.next();								//记录住每一个元素
			if(!newList.contains(obj)) {						//如果新集合中不包含老集合中的元素
				newList.add(obj);								//将该元素添加
			}
		}
		
		return newList;
	}

这里需要知道:

remove和contains底层都是依赖的equals方法,需要在javaBean中重写equals方法才可以,不然原equals根据地址值判断,操作无法达到理想效果。

12.LinkedList的特有方法

      public void addFirst(E e)及addLast(E e)
      public E getFirst()及getLast()
      public E removeFirst()及public E removeLast()
      public E get(int index);

13.栈和队列          数组和链表

14.LinkedList模拟栈结构(先进后出)

案例代码:

新建一个类Stack:

@SuppressWarnings({ "rawtypes", "unchecked" })
public class Stack {

	private LinkedList list = new LinkedList();

	/*
	 * 模拟进栈方法
	 */
	public void in(Object object) {
		list.addLast(object);
	}

/*
 * 模拟出栈方法
 */
	public Object out() {
		Object removeLast = list.removeLast();
		return removeLast;
	}

/*
 * 模拟判断是否为空方法
 */
	public boolean isEmpty() {
		return list.isEmpty();
	}
}

再调用封装好的方法实现功能:

Stack stack = new Stack();
		stack.in("a");
		stack.in("b");
		stack.in("c");
		stack.in("d");
		while (!stack.isEmpty()) {
			System.out.println(stack.out());
		}

15.泛型

泛型好处

    1.提高了安全性(运行时期的错误转换到编译期)

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

   没有用泛型限定能够输入的类型,在遍历过程中如果输出的时候进行强转,会报错无法强转。   2. 省去强转的麻烦 

<>中必须是引用数据类型

后面的泛型可以省去不写()

案例代码:

public static void main(String[] args) {
		ArrayList<Person> arrayList = new ArrayList<>();
		arrayList.add(new Person("张三", 18));
		arrayList.add(new Person("张四", 19));
		arrayList.add(new Person("张五", 20));
		arrayList.add(new Person("张六", 21));
		ListIterator<Person> iterator = arrayList.listIterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next().getAge() + iterator.next().getName());
		}
		while (iterator.hasPrevious()) {
			Person next = iterator.previous();
			System.out.println(next.getName() + next.getAge());
		}
	}

输出结果如下:18张四
                           20张六
                           张六21
                           张五20
                           张四19
                           张三18

如果不把对象返回,而是不断调用方法,指针索引会向后继续走。调用的方法其实不是一个同对象的。而且,一段调用结束,需要用previous让指针反向走才可以读取到数据。

16.泛型类,泛型方法和泛型接口

public class Tool<Q> {
	private Q q;

	public Q getObj() {
		return q;
	}

	public void setObj(Q q) {
		this.q = q;
	}

	public <T> void show(T t) {
		System.out.println(t);
	}

	public static <W> void test(W w) {
		System.out.println(w);
	}

}

泛型类:public class 类名<泛型类型1,…>。

泛型方法: public <泛型类型> 返回类型 方法名(泛型类型 变量名)。泛型推荐和类的泛型一样,如果不一样,要在权限修饰符后面添加自己的泛型

泛型静态方法:泛型不能和泛型类的一样,因为static在创建的时候就加载了,不确定先后顺序,所以需要自己在static后面加泛型

案例代码:

interface inter<T> {
	public void show(T t);
}

class Demo implements inter<String> {

	@Override
	public void show(String t) {
		System.out.println(t);
	}

}
// class Demo<T> implements inter<T> {
//
// @Override
// public void show(T t) {
// System.out.println(t);
// }
//
// }

泛型接口:public interface 接口名<泛型类型> 一般推荐实现类不带泛型,因为没必要

17.限定通配符

	public static void main(String[] args) {
		// 当右边的泛型是不确定的时候,左边可以指定为?
		// ArrayList<?> arrayList = new ArrayList<>();
		// 父类Person 子类Student
		ArrayList<Person> list1 = new ArrayList<Person>();
		list1.add(new Person("张三", 12));
		list1.add(new Person("李四", 13));
		list1.add(new Person("王五", 14));
		ArrayList<Student> list2 = new ArrayList<Student>();
		list2.add(new Student("赵六", 15));
		list2.add(new Student("胡七", 15));
		// list2.addAll(list1);
		boolean addAll = list1.addAll(list2);
		System.out.println(list1);
	}

         A:泛型通配符<?>
         任意类型,如果没有明确,那么就是Object以及任意的Java类了(当右边的泛型不确定的时候,左边的泛型中就输入通配符)
         B:? extends E
         向下限定,E及其子类
         C:? super E
         向上限定,E及其父类 

 boolean addAll(Collection<? extends E> c) 
          将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。

        在上面的案例代码中,可以发现。子类作为 泛型的list集合可以全被添加到父类作为泛型的集合中,但是父类作为泛型的不能被添加到子类作为泛型的list集合中,查询addAll方法,可以看到,参数列表是?extend E,也就是说,它支持向下限定。

18.增强for循环

作用:简化数组和Collection的遍历 

原理:底层依赖是迭代器

简化为foreach

19.三种迭代能否删除

案例代码:

//1,普通for循环删除,索引要--
		/*for(int i = 0; i < list.size(); i++) {
			if("b".equals(list.get(i))) {
				list.remove(i--);							//通过索引删除元素
			}
		}*/
		
		//2,迭代器删除
		/*Iterator<String> it = list.iterator();
		while(it.hasNext()) {
			if("b".equals(it.next())) {
				//list.remove("b");							//不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
				it.remove();
			}
		}*/
		
		/*for(Iterator<String> it2 = list.iterator(); it2.hasNext();) {
			if("b".equals(it2.next())) {
				//list.remove("b");							//不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
				it2.remove();
			}
		}*/
		//3,增强for循环,增强for循环不能删除,只能遍历
		for (String string : list) {
			if("b".equals(string)) {
				list.remove("b");
			}
		}
		System.out.println(list);
	}

特别说明for循环:

	ArrayList<String> list = new ArrayList<>();
		list.add("10.1举国欢庆!");
		list.add("10.2举国欢庆!");
		list.add("10.3举国欢庆!");
for (int i = 0; i < list.size(); i++) {
			// System.out.println(list.get(i));
			list.remove(i--);
		}

在这个循环中,如果是list.remove(i)输出结果是10.2举国欢庆!

因为在删除掉第一条以后,索引下移到了1的位置,而以前1位置对应的元素因为前面空缺,所以上移到了以前0的位置,以前2位置的元素恰好到了1位置,即正好被删除。所以需要i--回查。

20.静态导入

import static java.util.Arrays.toString;

import java.util.Arrays

前者是静态导入,后者是导入

静态导入调用直接方法即可

导入类的话需要类调用方法

导入的方法必须是静态的,因为存在同名等问题,所以开发中一般不用。

21.可变参数

可变参数基本上是以数组格式传入的。

基本格式为:修饰符 返回值类型 方法名(数据类型…  变量名){}

public static void print(int ... arr) 

案例代码:

	public static void main(String[] args) {
		int[] arr = {11,22,33,44,55};
		//print(arr);
		print(11,22,33,44,55);
		System.out.println("---------------");
		//print();
	}
	
	/*public static void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}*/
	
	
	public static void print(int ... arr) {			//可变参数其实是一个数组
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}

功能:定义数组的时候不知道定义多少个参数的时候使用。比一般数组参数强大的地方在于他可以直接接受元素形式的数组。

在接受元素形式的数组时,元素对着前面的参数进行分配,剩下的元素全部给可变参数,如果可变参数在最前面,那么,后面的参数都取不到值。

22.数组转集合asList

案例代码:

	public static void main(String[] args) {
		//demo1();
		//demo2();
		//集合转数组,加泛型的
		ArrayList<String> list = new ArrayList<>();
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		
		String[] arr = list.toArray(new String[10]);		//当集合转换数组时,数组长度如果是小于等于集合的size时,转换后的数组长度等于集合的size
															//如果数组的长度大于了size,分配的数组长度就和你指定的长度一样
		for (String string : arr) {
			System.out.println(string);
		}
	}

	public static void demo2() {
		//int[] arr = {11,22,33,44,55};			
		//List<int[]> list = Arrays.asList(arr);			基本数据类型的数组转换成集合,会将整个数组当作一个对象转换
		//System.out.println(list);
		Integer[] arr = {11,22,33,44,55};					//将数组转换成集合,数组必须是引用数据类型
		List<Integer> list = Arrays.asList(arr);
		System.out.println(list);
	}

	public static void demo1() {
		String[] arr = {"a","b","c"};
		List<String> list = Arrays.asList(arr);				//将数组转换成集合
		//list.add("d");									//不能添加
		System.out.println(list);
	}

数组转集合:必须是引用数据类型,基本数据类型只能输出地址值。

在数组转成集合的时候,不能进行修改操作,会报出如下错误:

Exception in thread "main" java.lang.UnsupportedOperationException

集合转换成数组:如果数组长度小于等于集合的元素个数,就会自动补全全部转换。如果数组长度大于集合元素个数,就会给一部分赋值,其余为null。

23.嵌套集合

案例代码:

ArrayList<ArrayList<Person>> arrayList = new ArrayList<>();
		ArrayList<Person> list = new ArrayList<>();
		list.add(new Person("张三", 15));
		list.add(new Person("李四", 16));
		list.add(new Person("王五", 17));
		ArrayList<Person> list2 = new ArrayList<>();
		list2.add(new Person("赵六", 18));
		list2.add(new Person("胡七", 19));
		list2.add(new Person("李八", 20));
		arrayList.add(list);
		arrayList.add(list2);
		for (ArrayList<Person> clazz : arrayList) {
			for (Person person : clazz) {
				System.out.println(person);
			}
			System.out.println("--------");
		}

嵌套并遍历输出

猜你喜欢

转载自blog.csdn.net/YooFale/article/details/82928234