IO流data流和对象流
Data流(字节节点流)
- 读写基本数据类型+String类型数据(需要传输有数据类型的数据时用)
- 是字节流功能流的一种
- DataInputStream 新增方法: readXxx()
- DataOutputStream 新增方法: writeXxx()
- 存在新增方法不能发生多态
- 先写出再写入
- EOFException 文件有,内容读入不到,必须读入的是写出的源文件
public static void main(String[] args) throws IOException {
//write("D:/data.txt");
read("D:/data1.txt");
}
//读入
public static void read(String path) throws IOException{
//1.输入流 数据类型+数据
DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream(path)));//Buffered缓冲流包裹
//2.读入
int i=in.readInt();
boolean b=in.readBoolean();
String s=in.readUTF();
System.out.println(i+"-->"+b+"-->"+s);
//3.关闭
in.close();
}
//写出
public static void write(String path) throws IOException{
//1.输出流
DataOutputStream out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.准备数据
int i=101;
boolean f=false;
String s="哈哈";
//3.写出 写出和读入的顺序要保持一致
out.writeInt(i);
out.writeBoolean(f);
out.writeUTF(s);
//4.刷出
out.flush();
//5.关闭
out.close();
}
对象流: Object 保存数据类型+数据
字节的功能流:当想要传输|读写对象类型数据的时候,可以使用一个对象流
序列化: 把对象类型的数据转化为可存储|可传输的状态的过程
ObjectInputStream() 反序列化输入流 新增方法: readObject()
ObjectOutputStream() 序列化输出流 新增方法: writeObject()
注意:
1.先序列化后反序列化
2.序列化反序列读写顺序一致
3.不是所有的类都能序列化 java.io.Serializable 空接口
4.不是所有的属性都需要序列化 transient
5.static内容不会被序列化
6.如果父类实现Serializable接口,子类中可以序列化所有内容
如果子类实现Serializable接口,但是父类没有实现,子类只能序列化子类独有的内容
public static void main(String[] args) throws IOException, ClassNotFoundException {
write("D:/object.txt");
read("D:/object.txt");
}
//反序列化输入
public static void read(String path) throws IOException, ClassNotFoundException{
//1.输入流
ObjectInputStream is=new ObjectInputStream(new BufferedInputStream(new FileInputStream(path)));
//2.读入
Object p= is.readObject();
int[] arr= (int[]) is.readObject();
if(p instanceof Person){
Person person=(Person)p;
System.out.println(person.getName());
}
System.out.println(p);
System.out.println(Arrays.toString(arr));
//3,关闭
is.close();
}
//序列化输出
public static void write(String path) throws IOException{
//1.输出对象信息
ObjectOutputStream os=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(path)));
//2.准备数据
Person p=new Person("冬冬",18);
int[] arr={1,2,3,4};
//3.输出
os.writeObject(p);
os.writeObject(arr);
//4.刷出
os.flush();
//5.关闭
os.close();
p.setAge(100);
}
}
class Person implements Serializable{
private String name;
private static int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 + "]";
}
IO流: 重点:字节流的使用,了解其他流的特点
- 字节流 : 可以读写任意内容,万能流
- 字符流 程序到文件 :只能读写存储文本内容
- 节点流:
- 缓冲流 Buffered :字节流都包裹一个缓冲流使用,提高读写效率
- 基本数据类型流 Data流 : 读写存储基本 数据类型数据|String
- 对象流:Object流 : 读写存储基本对象类型数据
容器|集合:
数组: 存储多个数据
数据类型相同
长度不可变
有序(索引)
容器: 存储多个数据
长度可以随着内容的多少进行改变
可以存储任意类型的数据
Collection存储单个数据的容器体系
Map 键值对形式数据的容器体系
自定义的容器类: 只能存储字符串类型的数据
添加功能
修改数据
查询数据
public static void main(String[] args) {
MyContainer container=new MyContainer();
container.add("钢铁侠");
System.out.println(container.size());
container.add("蜘蛛侠");
System.out.println(container.size());
container.add("猪猪侠");
System.out.println(container.size());
System.out.println(container.get(0));
System.out.println(container.get(1));
System.out.println(container.get(2));
System.out.println(container);
container.delete(1);
System.out.println(container);
}
}
//自定义容器类
class MyContainer{
//字符串数组,存储容器中的数据
private String[] arr;
//存储容器中数据的个数
private int size;
public MyContainer() {
arr = new String[0];
}
/*
*
*/
public String get(int index) {
if(index<0 || index>=size){
return "数组索引越界!!!";
}
return arr[index];
}
/*
* 存储数据:
* 返回值:不需要 参数:String
*/
public void add(String value) {
//备份原数组的地址
String[] temp=arr;
arr=new String[size+1];
//原数组中数据拷贝到新数组对应位置
for(int i=0;i<=size-1;i++){
arr[i]=temp[i];
}
//把参数赋值给数组的最后位置
arr[size]=value;
//长度+1
size++;
}
//删除方法
//返回值:没有 参数:根据索引删除
public void delete(int index){
if(index<0 || index>=size){
throw new ArrayIndexOutOfBoundsException( "数组索引越界!!!");
}
String[] temp=arr;
arr=new String[size-1];
//根据索引循环,判断当前索引值是否与要删除的数据的索引相同
for(int i=0;i<=size-1;i++){
if(i>=index){
if(i==index){
continue;
}
arr[i-1]=temp[i];
}else{
arr[i]=temp[i];
}
}
size--;
}
public int size(){
return this.size;
}
@Override
public String toString() {
return "MyContainer [arr=" + Arrays.toString(arr) + ", size=" + size + "]";
}
Collection 接口 容器体系的上层接口
Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。
一些 collection 是有序的,而另一些则是无序的。
容器类中可存放不同的类型的数据,但是必须都为引用数据类型的数据,基本数据类型会自动装箱
- 遍历:
- 1.增强for
- 2.迭代器
public static void main(String[] args) {
Collection col=new ArrayList();
Collection col2=new ArrayList();
col.add(123);
col.add("哈哈");
col.add(false);
col.add('c');
// boolean add(E e)
col2.add(1);
col2.add(2);
col2.add(3);
System.out.println(col);
col.addAll(col2);
System.out.println(col);
//boolean contains(Object o)
System.out.println(col.contains("哈哈"));
System.out.println(col.containsAll(col2));
// boolean remove(Object o)
System.out.println(col.remove(123));
System.out.println(col);
//for..each
for(Object o:col){
System.out.println(o);
}
//2.迭代器
//1.获取迭代器对象
Iterator it=col.iterator();
//2.判断是否存在下一个元素
while(it.hasNext()){
//3.获取元素
System.out.println(it.next()); //获取下一个元素
}
}
List 子接口
-
有序(索引)可重复
-
新增了一些根据索引操作的方法
-
遍历方式:
-
1.增强for
-
2.迭代器
-
3.普通for 根据索引遍历
public static void main(String[] args) {
//添加泛型 增可读性
List<Integer> ls=new ArrayList();
//存储班级学生分数
ls.add(2);
ls.add(0);
ls.add(1);
ls.add(4);
ls.add(3);
System.out.println(ls);
//add(index, element) 添加
ls.add(3, 3);
System.out.println(ls);
//E set(int index, E element) 修改
ls.set(5, 5);
System.out.println(ls);
// E get(int index) 获取
System.out.println(ls.get(2));
// E remove(int index)
//当容器中的数据也是整数时候,以索引为主
//下课测试,如果出现多个相同的值,移出时候删除多个,还是第一个
System.out.println(ls.remove(2));
System.out.println(ls);
//List<E> subList(int fromIndex, int toIndex) 不包含结束索引
System.out.println(ls.subList(1, 4));
System.out.println(Arrays.toString(ls.toArray()));
System.out.println(ls.toArray()[1]);
//普通for
for(int i=0;i<=ls.size()-1;i++){
System.out.println(ls.get(i));
}
/*
* 定义一个容器,存储你喜欢的漫威人物,如果有灭霸,就添加一个惊奇队长
*/
}
List 接口下的实现类:
-
List接口的实现类,有序可重复
-
ArrayList
-
底层实现: 由可变数组数组实现,通过数组拷贝实现容器可以根据内容进行动态扩容
-
优点: 遍历和获取的时候效率高,因为数据根据索引操作效率高
-
缺点: 增删效率低,大量涉及到数组拷贝问题
-
扩容: 使用Arrays的copyOf方法进行扩容,每次扩容原容量的1.5倍
-
int newCapacity = oldCapacity + (oldCapacity >> 1); 新的容量是老容量的1.5倍
-
新增方法: 没有新增方法,可以多态
-
应用场景:
-
单线程环境下,在大量做查询的业务下,适合使用ArrayList容器
-
Vector:
-
和ArrayList非常像
-
区别:1.ArrayList线程不安全,效率较高,Vector线程安全的,效率较低
-
2.扩容是每次扩容原容量的2倍,ArrayList1.5倍
*应用场景:多线程环境下,保证数据安全,大量做查询适合使用Vector -
LinkedList
-
底层实现:
-
优点:
-
缺点:
-
扩容:
-
新增方法:
public static void main(String[] args) {
ArrayList<Person> ls=new ArrayList();
ls.add(new Person("张三",18));
ls.add(new Person("李四",18));
ls.add(new Person("王五",20));
System.out.println(ls);
//构建一个list容器,存储Person类型的数据判断,名字叫做张三,年龄18岁的人在容器中的索引位置
System.out.println(ls.indexOf(new Person("张三",18)));
//默认调用equals方法比较的地址,重写equals方法,让person比较的时候比较内容非地址
}
}
class Person{
private String name;
private int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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 + "]";
}
@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;
}