Java之IO流中Data流、对象流以及Collotion接口下Arrays LIst、LikedList的学习

IO流

Data流

读写基本数据类型+String类型数据,是字节流功能流的一种

请注意:Data流的输出和输入的顺序必须保持一致

类名新增方法
DataInputStreamreadXxx()
DataOutputStreamwriteXxx()

由于有新增方法,我们不用他父类去接收他的对象

XXX是代表四类八种基本数据类型,此外还可以使用UTF读取字符串,示例如下;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//重打代码:先写出在写入
public class DataDemo01 {
	public static void main(String[] args) {
		
	}
	//写出
	public static void write(String path) throws IOException{
		//1.序列化输出流
		DataOutputStream out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
		//2.准备数据
		short s=1;
		int   i=1;
		long  l=1L;
		float f=1.0f;
		double d=2.0;
		char   c='c';
		boolean b=true;
		String str="哈哈";
		//3.写出  写出和读入的顺序要一致
		out.writeShort(s);
		out.writeInt(i);
		out.writeLong(l);
		out.writeFloat(f);
		out.writeDouble(d);
		out.writeChar(c);
		out.writeBoolean(b);
		out.writeUTF(str);
		//4.刷出
		out.flush();
		//5.关闭
		out.close();
	}
	
	//写入
	public static void read(String path) throws IOException{
		//1.选择输入流
		DataInputStream is=new DataInputStream(new BufferedInputStream(new FileInputStream(path)));
		//2.写入,按写出的顺序写入
		short 	s=is.readShort();
		int   	i=is.readInt();
		long  	l=is.readLong();
		float 	f=is.readFloat();
		double	d=is.readDouble();
		char  	c=is.readChar();
		boolean b=is.readBoolean();
		String 	str=is.readUTF();
	    //3.关闭
		is.close();
	}
}

对象流

对象流:Object保存数据类型+数据,是字节的功能流,可以使用一个对象流。

序列化:把对象类型的数据转化为可存储的|可传输的状态的过程

类名称呼新增方法
ObjectInputStream反序列化输入流readObject()
ObjectOutputStream序列化输出流writeObject()

注意:

  1. 先序列化后反序列化
  2. 序列化和反序列化前后顺序一致
  3. 不是所有的类都能序列化
    1. 类实现序列化,必须实现java.io.Serializable,该接口是一个空接口
  4. 不是所有的属性都需要序列化
    1. 可以在前面加上transient就不会被序列化
  5. static修饰的内容不会被序列化
  6. 如果父类实现Serializable接口,子类可以序列化所有内容。如果子类实现Serializable接口,但是父类没有实现,子类只能序列化子类独有的内容。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectDemo02 {
	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		//1.文件先写出
		write("d://one.txt");
		//2.文件写入
		read("d://one.txt");
	}
	
	
	

	//构建一个方法,.作为序列化输出
	public static void write(String path) throws FileNotFoundException, IOException{
		//1.选择序列化输出流
		ObjectOutputStream os=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
		//2.创建对象
		Person p1=new Person("测试一",15,25);
		String[] p2={"文本测试"};
		//3.把对象存储到  文件中
		os.writeObject(p1);
		os.writeObject(p2);
		//4.刷出
		os.flush();
		//5.关闭
		os.close();
		//6.设置  static 修饰的值k
		//如果k的值被写入到文件中,读取的时候,k的值应该是不会变
		//但是如果kd值没有被写入到文件,则应该取静态变量的最后一次
		p1.setK(100);
		
		
	}
	//构建一个方法,作为反序列化输入
	public static void read(String path) throws FileNotFoundException, IOException, ClassNotFoundException{
		//1.选择一个反序列化输入流
		ObjectInputStream is=new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
		//2.读取内容,按顺序读
		Object p1=is.readObject();
		if(p1 instanceof Person){
			Person p=(Person)p1;
			//打印
			System.out.println(p);
			//name成功获取,
			//age获取不到,因为被transient修饰
			//k获取到最后一个值,因为是静态的,只能获取到最新的
		}
		String[] s=(String[])is.readObject();
		//3.关闭流
		is.close();
		//4.打印
	}
	

	
	
}
//构建一个测试类  实现Serializable接口,是类具有序列化的能力
class Person implements Serializable{
	private  String name;
	private  transient int age;
	private  static int k;
	public int getK() {
		return k;
	}
	public void setK(int k) {
		this.k = k;
	}

	
	
	public Person(String name, int age, int k) {
		super();
		this.name = name;
		this.age = age;
		this.k = k;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	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 String toString() {
		return "Person [name=" + name + ", age=" + age + ", k=" + k + "]";
	}
}

小结

IO流:重点在于字节流的使用,了解其他流的特点

名称分类特点
字节流字节流可以读写任意内容万能流
字符流字符流程序到文件,只能读写存储文本的内容
缓冲流节点流缓冲流包裹一个字节流使用,提高读写效率
基本数据类型流字节功能流读写基本数据类型以及String类型
对象流字节功能流读写基本数据类型以及对象类型数据,但一般由于对象

容器

类别特点
数组存储多个数据
数据类型相同
长度不可变
有序(索引)
容器存储多个数据
长度可以随着内容的多少变动
可以存储任意类型的数据

两大体系

类型优点
Collection存储单个数据的容器体系
Map键值对形式数据的容器体系

自定义容器

要求:只能存储字符类型的数据,实现添加、删除、修改、查询的功能。

代码如下:

import java.util.Arrays;

public class App01 {
	public static void main(String[] args) {
		MyContainer my=new MyContainer();
		my.add("钢铁侠");
		System.out.println(my);
		my.add("闪电侠");
		System.out.println(my);
		my.add("绿箭侠");
		System.out.println(my);
		my.delete(1);
		System.out.println(my);
	}
}


//自定义容器类
class MyContainer{
	//1.字符串数组,存储容器中数据
	private String[] arr;
	//2.存储中的个数
	private int size;
	//3.在构造器中设置,初始长度为0
	public MyContainer() {
		super();
		// TODO Auto-generated constructor stub
		arr=new String[0];
	}
	//实现查询的功能
	//4.设置一个get器,用于获取当前索引位置下的元素
	public String get(int index){
		//判断是否有没有越界
		if(index>=size){
			return "越界";
		}
		return arr[index];
	}
	//实现修改的功能
	//5.设置一个set器,用于修改当前路径的下的内容
	public void set(int index,String str){
		//判断是否有没有越界
		if(index>=size){
			System.out.println("越界了,无法修改");
		}else{
			arr[index]=str;
		}
	}
	//实现单个元素的添加功能
	//6.设置一个add方法,用于添加数据
	public void add(String src){
		//备份原数组的地址
		String[] temp=arr;
		arr=new String[size+1];
		//原数组拷贝到对应的位置
		for(int i=0;i<size;i++){
			arr[i]=temp[i];
		}
		//把参数赋值给数组最后的位置
		arr[size]=src;
		//长度+1
		size++;
	}
	//7.根据索引删除一个元素
	public void delete(int index){
		//判断是否有没有越界
		if(index>=size){
			System.out.println("越界了,无法修改");
			return;		
		}
		//备份数据
		String[] temp=arr;
		//原数组长度-1
		arr=new String[size-1];
		//根据索引循环,判断是否索引值是否与要删除的数据的索引值相同
		for(int i=0;i<size;i++){
			if(i>=index){
				//如果相同跳出本次循环
				if(i==index){
					continue;
				}else{
				//否则把 原数组的后一个值给新数组的前一个位置
				arr[i-1]=temp[i];
				} 
			}else{
				arr[i]=temp[i];
			}
		}
	}
	
	@Override
	public String toString() {
		return "MyContainer [arr=" + Arrays.toString(arr) + ", size=" + size + "]";
	}
}

Collection接口

Collectio你是容器体系的上层接口

Collection表示一组对象,这些对象对象也称为Collection的元素.一些Collection允许有重复的元素,而另一些不允许。一些Collection是有序的,一些Collection是无序的。

Collection接口中需要实现的方法
类别方法
增加boolean add(E e)
boolean addAll(Collection<? extends E> c)
删除boolean remove(Object o)
boolean removeAll(Collection<?> c)
查询boolean contains(Object o)
boolean containsAll(Collection<?> c)
迭代Iterator iterator()
List接口下的实现类

与Collection接口是继承关系

ArraysList类

​ ArraysList时候List的实现类,我们通过这个类来学习这个类中的常用方法

​ ArrayList是List接口下实现的类

​ List接口的实现类有序可重复

ArrayList:

底层实现:可变数组实现,通过数组拷贝实现容器可以根据内容进行变动.。

优点:遍历和获取的效率高,因为数据根据索引操作效率高

缺点:增删效率低,大量涉及到数组拷贝问题

扩容:使用Arrays的copyOf方法进行扩容,每次扩容到原容量 的1.5倍,新的容量是老的容量的1.5倍。

	**新增方法**:没有新增方法,可以多态

应用场景:单线程的环境下,在做大量的查询业务,适合还是用ArrayList容器.

Vetor:

​ 和ArrayLis非常像

区别:

  1. ArrayList线程不安全,效率较高,Vector线程安全,效率较大

  2. 扩容是每次扩容到原来的2的被,ArrayList是1.5倍

    应用:多线程环境下,保证数据安全,大量查询适合使用Vector

ArrayList常用方法
import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo02 {
	public static void main(String[] args) {
		Collection co1=new ArrayList();//用实现的接口去接收实现类的对象
		Collection co2=new ArrayList();//用实现的接口去接收实现类的对象
		co1.add(1);
		System.out.println("添加1 打印");
		System.out.println(co1);
		co2.add("我很好");
		co1.addAll(co2);
		System.out.println("添加co2对象打印");
		System.out.println(co1);
		co2.clear();
		System.out.println("清除co2");
		System.out.println(co2);
		//判断是否包含
		System.out.println(co1.contains(1));
		//判断是否包含所有元素
		co2.add("我很好");
		co2.add("我好");
		System.out.println(co1.contains("我很好"));
		//判断是co1是否包含co2的所有元素
		co1.addAll(co2);
		System.out.println(co1);
		System.out.println(co1.containsAll(co2));
		//判断是否为空
		System.out.println(co1.isEmpty());
		//移动指定元素的实例
		System.out.println(co2);
		co1.removeAll(co2);
		System.out.println(co1);
		//返回元素个数
		System.out.println(co1.size());
	}
}
List的遍历方式
普通For循环
import java.util.ArrayList;
import java.util.List;
public class ListDemo01 {
	public static void main(String[] args) {
		//添加泛型 增强可读性
		List<Integer> ls=new ArrayList<Integer>();
		//存储班级学生分数
		ls.add(2);
		ls.add(25);
		ls.add(56);
		ls.add(79);
		//打印结合中的所有内容
		//因为List重写了toString方法,可以直接打印
		System.out.println(ls.toString());
		//admin(index)
		//使用普通for做遍历
		for(int i=0;i<ls.size();i++){
			System.out.println(ls.get(i));
		}
	}
}
增强For循环
import java.util.ArrayList;
import java.util.List;
public class ListDemo01 {
	public static void main(String[] args) {
		//添加泛型 增强可读性
		List<Integer> ls=new ArrayList<Integer>();
		//存储班级学生分数
		ls.add(2);
		ls.add(25);
		ls.add(56);
		ls.add(79);
		//打印结合中的所有内容
		//因为List重写了toString方法,可以直接打印
		System.out.println(ls.toString());
		//admin(index)
		//使用增加for
		for(int x:ls){
			System.out.println(x);
		}	
	}
}
迭代器
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Demo02 {
	public static void main(String[] args) {
		// 定义一个容器,存储你喜欢的漫威人物
		//如果有灭霸,就添加一个惊奇队长
		List<String> list=new ArrayList<String>();
		//1.添加内容
		list.add("闪电侠");
		list.add("钢铁侠");
		list.add("黑寡妇");
		list.add("雷声");
		list.add("灭霸");
		list.add("绿箭侠");
		list.add("伸缩侠");
		//打印该List容器中的所有内容
		System.out.println(list);
		
		//2.遍历,使用迭代器,报错
		//2.1设置一个遍历器
		Iterator<String> it=list.iterator();
		//2.2判断条件为,是否有下一个元素
		for(;it.hasNext();){
			//3.判断是否有灭霸,如果有则添加,没有则不添加
			if("灭霸".equals(it.next())){//此行会报异常
				//4.添加元素
				System.out.println("和");
				list.add("惊奇队长");
			}
			
		}
		System.out.println(list);
	}
}

第29行会报异常,其中详细信息如下

Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
	at java.util.ArrayList$Itr.next(Unknown Source)
	at list03.Demo02.main(Demo02.java:29)

​ 这个是因为,不能有个"对象"同时操作同一个对象,官方文档中表示:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。其实就是it.next()it.hasnext(),在同时指向下一个对象时,系统会抛出异常.

​ 我们可以采用Java提供的另一个迭代器,列表迭代器

列表迭代器
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Demo02_01 {
	public static void main(String[] args) {
		// 定义一个容器,存储你喜欢的漫威人物
		//如果有灭霸,就添加一个惊奇队长
		List<String> list=new ArrayList<String>();
		//1.添加内容
		list.add("闪电侠");
		list.add("钢铁侠");
		list.add("黑寡妇");
		list.add("雷声");
		list.add("灭霸");
		list.add("绿箭侠");
		list.add("伸缩侠");
		//打印该List容器中的所有内容
		System.out.println(list);
		
		//2.遍历,使用迭代器,报错
		//2.1设置一个列表遍历器
		ListIterator<E> listIterator()  
		ListIterator<String> it=list.listIterator();
		//2.2判断条件为,是否有下一个元素
		while(it.hasNext()){
			if("灭霸".equals(it.next())){
				it.add("惊奇队长");
			}
		}
		System.out.println(list);
		//[闪电侠, 钢铁侠, 黑寡妇, 雷声, 灭霸, 惊奇队长, 绿箭侠, 伸缩侠]
		//我们发现<惊奇队长>是放在<灭霸>的后面,这个是因为遍历的时候,就把
		//<惊奇队长>添加进去
List接口下实现类
LinkedList

底层实现:底层是由双向链表结构实现的

优点:做增删效率高

缺点:做查询效率低

新增方法:新增了一些有链表头和链表尾的方法

equqal方法

​ 我们通常喜欢比较的时候,使用equals方法,而equals方法如果没有进行重写,比较的这是地址,我们可以尝试写一个通过euqals方法比较的是对象的内容而不是地址.

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

public class Demo03 {
	public static void main(String[] args) {
		//创建一个ArrayList对象,并且限制容器准许存储对象
		ArrayList<Person> ls=new ArrayList();
		//1.添加对象
		ls.add(new Person("西沃",19));
		ls.add(new Person("东土",25));
		ls.add(new Person("北丐",25));
		ls.add(new Person("南帝",25));
		System.out.println(ls);
		//如何判断索引位置   indeOf
		System.out.println(ls.indexOf(new Person("东土",25)));//预计:1 结果:-1
		//发现无法直接通过对象中的属性去查找相对应的位置,因为这个是一个新对象

		//如果我们想要实现在equals方法中比较得出非地址的内容,就需要重写该该方法
		//一般来说,我们可以直接在 调用的类中  重写该方法,以实现比较非地址的内容
		//通过迭代遍历,我们可以取到值
		Iterator<Person> it=ls.iterator();
		while(it.hasNext()){
			//取出新对象(下图new的对象)中的 name属性和 age属性,与原对象(前面new的对象)进行相比较
			System.out.println(it.next().equals(new Person("东土",25)));
		}		
	}
}


class Person{
	private String name;
	private int age;
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	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() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	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 false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}
常用方法(不重要)
import java.util.LinkedList;

public class LinkList {
	public static void main(String[] args) {
		//创建一个LinkedList对象
		LinkedList<Character> ls=new LinkedList();
		//添加元素
		ls.add('a');
		ls.add('b');
		ls.add('t');
		ls.add('k');
		ls.add('w');
		ls.add('y');
		System.out.println(ls);//[a, b, t, k, w, y]
		//移出指定位置的元素 序号为3的元素被删除
		ls.remove(3);
		System.out.println(ls);//[a, b, t, w, y]
		//其他用法与 ArrayList相同
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值