java集合和io笔记

2 篇文章 0 订阅
1 篇文章 0 订阅

视频时需要归纳的主要问题:

一、集合:

1.Collection接口常用的方法有哪些,集合的具体种类有哪些?
有序的
add():往list集合中添加元素
remove(Object o):从当前集合中移除o元素
removerAll(Collection coll1): 差集 从当前集合中移除coll1中所有元素
size():获取集合大小
Iterator():返回一个接口实现类的对象 ,来实现集合的遍历,
IsEmpty():判断集合是否为空
contaions(Object o):判断当前集合是否包含o (判断内容)
contaionsAll(Colleation coll1):判断形参coll1中的所有元素是否都存在于当前集合中。
retainAll(Collection coll):交集 获取当前集合和coll1集合的交集 并返回给当前集合
equals(Collection coll1)判断两个集合内容是否一致
hashCode():返回当前对象的哈希值
toArray():集合–》数组
Arrays.asList(new String []{“111”,“222”});数组–》集合
2.迭代器Iterator的使用方式和需要注意的问题
@Test
public void test1(){
Collection col = new ArrayList<>();
col.add(123);
col.add(456);
col.add(new String(“Tom”));
Iterator iterator = col.iterator();
while (iterator.hasNext()){
if ((iterator.next()).equals(123)) {
iterator.remove();
}
}
iterator=col.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
调用hasNext()返回指针下一个是否存在调用然后调用next()获取指针下一个元素
注意:每次调用一个新的iterator()方法都会得到一个新的迭代器 默认游标都会在集合第一个之前
内部定义了一个remove()方法 可以在遍历的时候 删除集合当中的元素 是迭代器里面的remove()
一次遍历只能调用一次remove()注意指针的指向
3.foreach语法遍历的用法
jdk5.0开始提供
用于遍历集合和数组
Collection col = new ArrayList<>();
col.add(123);
col.add(456);
col.add(new String(“Tom”));
for(Object obj:col){
System.out.println(obj);
}
4.List的常用实现类有哪些,有什么区别
特点:有序的,可重复
ArrayList 主要实现类 线程不安全 效率高 底层使用的还是数组 Object[] elementData
用于检索数据
LinkedList 对于频繁的插入 删除操作 使用此类效率比ArrayList高 底层使用双向链表存储
Vector :作为List接口的古老实现类 线程安全 效率低 底层实现和ArrayList一样
5.描述ArrayList源码的大致实现(最好模拟手动实现增、删、改、查、遍历元素的基本功能),初始大小是多少,什么是扩容,源码如何扩容
增:
ArrayList li = new ArrayList();
li.add(123);
li.add(456);
li.add(“AA”);
li.add(new String(“Tom”));
li.add(123);

li.remove(0);
改:
li.set(1,“AA”);
查:
li.get(1);

jdk1.7 :Object[] elementData 初始大小为10  
jdk1.8之后Object[] elementData 初始化为{ }初始大小为0 等到调用add()方法时才会给一个长度为10的数组 并将数据添加到elementData
扩容:扩大Object[] elementData长度
判断当前所需数组最小长度和数组长度的大小需求
if (minCapacity - elementData.length > 0)
        		grow(minCapacity);如果所需最小长度大于数组长度就扩容
}
private void grow(int arg0) {
	int arg1 = this.elementData.length;//当前数组长度
	int arg2 = arg1 + (arg1 >> 1);//扩大到原来的1.5倍(默认)
	if (arg2 - arg0 < 0) {//扩大到原来的两倍
		arg2 = arg0;
	}

	if (arg2 - 2147483639 > 0) {
		arg2 = hugeCapacity(arg0);
	}
	将新的数组覆盖掉原来的
	更新
	this.elementData = Arrays.copyOf(this.elementData, arg2);

}

6.描述LinkedList源码的大致实现(最好模拟手动实现增、删、改、查、遍历元素的基本功能),初始大小是多少,什么是扩容,源码如何扩容
内部声明了Node类型的false和last属性,默认值为null
LinkedList list=new LinkedList();
list.add(123);将123封装到Node中 创建了Node对象
其中:Node定义为:
private static class Node {
E item;
Node next;
Node prev;

    			Node(Node<E> prev, E element, Node<E> next) {
        			this.item = element;
        			this.next = next;
        			this.prev = prev;
   		 	}
		}

7.简述ArrayList和LinkedList的优缺点
ArrayList 主要实现类 线程不安全 效率高 底层使用的还是数组 Object[] elementData
LinkedList 对于频繁的插入 删除操作 使用此类效率比ArrayList高 底层使用双向链表存储
8.Set是什么,有什么特点,有哪些具体的子类,子类各自有功能上的区别
特点:无序的(不等于随机性 存储的数据在底层数组中并非按照数组索引的顺序添加 而是根据数据的哈希值)
不可重复的:保证添加的元素按照equals()判断时 不能返回true 即相同的元素只能存放 一个
HashSet:作为Set接口的主要实现类 线程不安全的;可以存储null值
LinkedHashSet:作为HashSet的子类 遍历其内部数据时可以按照添加的顺序遍历
LinkedHasdSet作为HashSet的子类 在添加数据的同时 每个数据还维护了两个引
用,记录了这个数据的前一个数据和后一个数据
对于频繁的遍历操作 linkedHashSet效率高于HashSet
TreeSet:可以按照添加对象的指定属性进行排序(放入TreeSet内的数据是同一个属性)
两种排序方式:自然排序(实现Comparable接口)和定制排序(Comparator )

9.简述HashSet添加元素的步奏(hashCode和equals)
要求:向Set(主要指:HashSet,LinkedHashSet)中添加的数据,其所在的类一定要重写hashCode()和equals()方法
要求:重写的hashCode()和equals()尽可能保持一致性。相等的对象必须有相等的散列码。
重写两个方法的小技巧:对象中用作equals()方法比较的Field,都应该用来计算hashCode值
我们要向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值
此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置判断数组此位置上是否有元素
如果此位置上没有其他元素,元素添加成功
如果此位置上有其他元素(或以链表形式存放多个元素),比较元素a与元素b
的hash值;
如果hash值不相同,则元素a添加成功
如果hash值相同,进而需要调用元素a所在的equals()方法:
equals() 返回true 元素a添加失败
equals() 返回false 元素a添加成功
以链表的方式进行存储
jdk7 元素a放到数组中 指向原来的元素
jdk8 原来的元素在数组中 指向元素a
总结:七上八下
HashSet底层:数组+链表的结构。
//在list内去重
public static List duplicateList(List list){
HashSet set =new HashSet();
set.addAll(list);
return new ArrayList(set);
}

public static void main(String[] args) {
List list=new ArrayList();
list.add(new Integer(1));
list.add(new Integer(2));
list.add(new Integer(3));
list.add(new Integer(1));
//注意如果是对象的话就要重写hashCode()和equals()
List list1 = duplicateList(list);
Iterator iterator = list1.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
10.LinkedHashSet的基本操作有哪些
LinkedHasdSet作为HashSet的子类 在添加数据的同时 每个数据还维护了两个引用,记录了这个
数据的前一个数据和后一个数据
优点:对于频繁的遍历操作 linkedHashSet效率高于HashSet
11.TreeSet的特点和基本操作,如何定制排序
底层:红黑树
1.向TreeSet中添加的数据 要求是相同类的对象
2.两种排序方式:自然排序(实现Comparable接口) 和 定制排序(Comparator)
3.自然排序中 比较两个对象是否相同的标准为:compareTo()返回0 不再是equals()
4.定制排序中,比较两个对象是否相同的标准为:compare()返回0 不再是equals()
Comparator com=new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof User && o2 instanceof User){
User user1=(User)o1;
User user2=(User)o2;
return Integer.compare(user1.getAge(), user2.getAge());
}else {
throw new RuntimeException(“输入的数据类型不匹配!”);
}
}
};
TreeSet set=new TreeSet(com);
set.add(new User(“Tom”,12));
set.add(new User(“Jerry”,33));
set.add(new User(“Jack”,44));
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}

}
12.Map的特点,常用的实现类有哪些,有什么区别
Map:双列数据,存储于key-value对的数据
Map中的key:无序的 不可重复的 使用Set存储所有的key —>key所在的类要重写 equals()和 HashCode()
Map中的value:无序的 可重复的 使用Collection存储所有value–》value所在类要重写equals()
一个键值对:构成了一个Entry对象
Map中的entry:无序的 不可重复的 使用Set存储所有的entry
HashMap:作为Map的主要实现类 线程不安全 效率高 存储null的key-value对
LinkedHashMap :保证遍历map元素时,可以按照添加的顺序实现遍历。
原因:在原有的HashMap底层结构基础上 添加了一对指针 指向前一个和后一 个元素
对于频繁的遍历操作 此类执行效率高于HashMap
底层:jdk 7之前 数组+链表
jdk8 数组+链表+红黑树
TreeMap: 存储有序键值对 保证按照添加的key-value对进行排序 实现排序遍历 此时考虑
key的自然排序和定制排序
底层:红黑树
Hashtable:作为古老实现类 线程安全 效率低 不能存储null的key-value 对
Properties 常用来处理配置文件 key和value都是string类型

面试题:
1.HashMap底层实现原理:jdk 7之前 数组+链表
jdk8 数组+链表+红黑树
2.HashMap和Hashtable的异同:
HashMap作为Map的主要实现类 线程不安全 效率高 存储null的key-value对、
Hashtable:作为古老实现类 线程安全 效率低 不能存储null的key-value 对
3.CurrentHashMap 与 Hashtable 的异同?
13.HashMap的常用方法和基本操作(增删改查,遍历元素等等)
添加、删除、修改操作:
Object put(Object key,Object value):
将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据
元素查询的操作:
Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等
元视图操作的方法:
Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合
实操:
HashMap map = new HashMap();
//添加
map.put(123, “AA”);
map.put(234, “BB”);
map.put(345, “CC”);
//添加
HashMap map1 = new HashMap();
map1.put(111, “wowowo”);
map1.put(123, “MM”);
//查询
System.out.println(map1.get(111));
//修改
map1.putAll(map);
//删除
Object o = map1.remove(123);
//clear()清空
map.clear();//底层数组还在只是数据被清空了,所以map还在
System.out.println(map.size());
System.out.println(o);
System.out.println(map);
System.out.println(map1);
//keySet()遍历所有的key集
Set set = map.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
// System.out.println(map.get(iterator.next()));
System.out.println(iterator.next());
}
//遍历所有的values集 values()
Collection values = map.values();
Iterator iterator1 = values.iterator();
while (iterator1.hasNext()) {
System.out.println(iterator1.next());
}
//entrySet()遍历集合中所有key-value
Set set1 = map.entrySet();
Iterator i1 = set1.iterator();
while (i1.hasNext()) {
Map.Entry aa=(Map.Entry)i1.next();
System.out.println(aa.getKey()+"—>"+aa.getValue());
}

13.简单描述HashMap的底层实现原理(不要求手动实现),和hashSet对比有什么区别。
jdk7为例说明:
HashMap map=new HashMap();
在实例化以后,底层创建长度是16的一维数组Entry[] table
…可能已经执行过多次put…
map.put(key1,value1);
首先,我们调用key1所在类的HashCode()计算key1的哈希值 ,此哈希值经过某种算法以后得到在Entry数组中存放的位置,如果此位置上数据为空,此时的key1-value1添加成功
情况1
如果此位置数据不为空(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
如果key1的哈希值与已经存在的数据的哈希值都不相同 key1-value1添加成功。
情况2
如果key1的哈希值与已经存在的数据的哈希值都相同 继续比较 调用key1所在类的equals()方法比较:返回false key1-value1添加成功。
返回true 使用key1-value1替换相同的key-value值
情况3
补充:关于情况2和3 此时key1-value1和原来的数据以链表的方式存储
在不断添加过程中 会涉及到扩容问题 当超出临界值(且要存放的位置非空)时, 扩容到原来的两倍 并将原来的数据复制过来
jdk8相较于jdk7在底层实现方面的不同
1.new HashMap():底层没有创建一个长度为16的数组
2.jdk8 底层数组是Node[] 而非Entry[]
3.首次调用put()方法时,底层创建一个长度为16的数组
4.jdk7底层结构只有:数组+链表,jdk8中底层结构:数组+链表+红黑树
当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组长度>64
时此时此索引位置上的所有数据改为使用红黑树存储
DEFAULT_INITIAL_CAPACITY:HashMap的默认容量,16
DEFAULT_LOAD_FACTOR :HashMap默认加载因子:0.75
threshold:扩容的临界值:16*0.75=12
TREEIFY_THRESHOLD =:Bucket 中链表长度大于该默认值,转换为红黑树:8
MIN_TREEIFY_CAPACITY :同种的Node被树化时最小的hash表容量
和HashSet的区别:
HashSet相同元素时添加失败
HashMap相同元素时会将新的元素覆盖掉原来的元素

14.简单描述LinkedHashMap底层实现原理
HashMap子类
内部类Entry
用于频繁的遍历
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;//能够记录添加元素是的顺序
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
15.TreeMap添加元素的方式
TreeMap:
向TreeMap中添加key-values要求key必须是同一个类创建的对象
因为要按照key进行排序:自然排序
实现Comparable接口;
定制排序:
public void TreeSetTest(){
TreeMap map = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof User1 && o2 instanceof User1){
User1 user1=(User1)o1;
User1 user11=(User1)o2;
return Integer.compare(user1.getId(), user11.getId());
}
throw new RuntimeException(“输入类型不一致”);
}
});
User1 u1=new User1(“wowo1”,12);
User1 u2=new User1(“wowo2”,13);
User1 u3=new User1(“wowo3”,14);
User1 u4=new User1(“wowo4”,15);
map.put(u1, 78);
map.put(u2, 88);
map.put(u3, 98);
map.put(u4, 89);
//遍历
Set set = map.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object o = iterator.next();
Map.Entry entry=(Map.Entry)o;
System.out.println(entry.getKey()+"----"+entry.getValue());
}

}

16.Collections工具类的常用方法
collections是一个操作List,Map,Set集合的工具类
面试题:Collection和Collections的区别
Collection是一个创建集合的接口Collections是一个操作集合的工具类
常用方法:
reverse(list):反转list中元素的顺序
shuffle(list):对list集合元素进行随机排序
sort(list):根据元素的自然排序对指定List集合元素进行升序排序
sort(list,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
swap(list,int,int):将指定List集合中的i处元素和j处元素进行交换
frequenty(collection,Object);返回指定集合中指定元素出现的次数
copy(list desc,list src) desc是要复制的集合 src是被复制的集合
注意:desc长度一定要等于src长度
ArrayList list = new ArrayList();
list.add(1);
list.add(3);
list.add(5);
list.add(2);
List desc=Arrays.asList(new Object[list.size()]);
Collections.copy(desc, list);
System.out.println(desc);
Collections工具类中synchronizedList()方法将list转换为线程安全的
synchronizedHashMap()方法map转换为线程安全的
//ArrayList线程不安全
//使用Collections工具类调用synchronizedList()转换为线程安全的
List list1 = Collections.synchronizedList(list);
//list1线程安全
二.IO流

1、 IO流的概念(什么是IO流,IO流的分类有哪些,主要的类或者接口对应有哪些)
流的基类:InputStream OutputStream Reader Writer
文件流:Filexxx
处理流:Bufferedxxx
数据单位分类:
字符流:char类型 Reader Writer 处理输入流和输出流
字节流 : byte 类型 inputStream OutputStream 处理输入流和输出流
数据流向分类:
输入流 :inputStream
输出流 :OutputStream
按照流的角色分类:
节点流 :直接作用在文件上FileInputStream FileOutputStream FileReader FileWriter
处理流:

缓冲流:作用在已有流上 BufferedInputStream  BufferedOutputStream BufferedReader BufferedWriter

转换流:将输入的字节流转换为输入的字符流 InputStreamReader 将输出字符流转换为输出字节流OutputStreamWriter
标准的输出输入流:System.in 标准的输入流 从键盘读取数据 System.out 标准的输出流 默认控制台输出
数据流:DateInputStream和DateOutputStream
	分别“套接”在inputStream和OutputStream子类的流上
	作用:用于读取或写出基本数据类型的变量或字符窜
对象流:ObjectInputStream ,ObjectOutputStream

2、 FileReader和FileWriter读写数据操作的代码
@Test
public void teatReaderFileWriter(){
//1.创建file类的对象,指明读入和写出的文件
FileReader fe=null;
FileWriter fw=null;
try {
File file = new File(“hello.txt”);
File file1 = new File(“hello1.txt”);
//2.创建流的对象
fe = new FileReader(file);
fw = new FileWriter(file1);
//3.读入和写出的操作
char[] arr=new char[1024];
int len=0;
while ((len = fe.read(arr)) != -1) {
fw.write(arr, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4,关闭流
try {
if (fw!=null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fe!=null) {
fe.close();
}
} catch (IOException e) {
e.printStackTrace();
}

    }
}

3、 FileInputStream和FileOutputStream的复制文件的方式
@Test
public void FileImg(){
FileInputStream from=null;
FileOutputStream to=null;
//创建File类指明读入和写出的对象
try {
File file = new File(“QQ图片20191021105340.jpg”);
File file1 = new File(“QQ图片201910211053401.jpg”);
//创建流对象
from = new FileInputStream(file);
to = new FileOutputStream(file1);
//读入和写出的操作
byte[] arr=new byte[1024];
int len=0;
while ((len = from.read(arr)) != -1) {
to.write(arr, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (to!=null) {
to.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (from!=null) {
from.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、 缓冲流实现文本文件和非文本文件的复制方式
@Test
public void FileBufferInputStream(){
String srcpath=“QQ图片20191021105340.jpg”;
String outputh=“QQ图片201910211053403.jpg”;
long start=System.currentTimeMillis();
Copy(srcpath, outputh);
long end=System.currentTimeMillis();
System.out.println(“复制过来所花时间” + (end - start));
}
public static void Copy(String srcpath,String outputh){
BufferedInputStream bufferedInputStream=null;
BufferedOutputStream bufferedOutputStream=null;
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream(new File(srcpath)));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File(outputh)));
byte[] bytes=new byte[1024];
int len=0;
while ((len=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedOutputStream!=null) {
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bufferedInputStream!=null){
bufferedInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}

    }

}

5、 转换流的使用
@Test
public void test5() {
FileInputStream fr=null;
FileOutputStream fout=null;
InputStreamReader in = null;
OutputStreamWriter out=null;
try {
fr = new FileInputStream(new File(“hello1.txt”));
fout=new FileOutputStream(new File(“hello3.txt”));
in = new InputStreamReader(fr,“UTF-8”);
out=new OutputStreamWriter(fout,“gbk”);
char[] c=new char[1024];
int len=0;
while ((len = in.read©) != -1) {
out.write(c, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
try {
if(fr!=null) {
in.close();
}

    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        if(fout!=null) {
            out.close();
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
}

6、 转换流和数据流的基本使用。
@Test
public void test6(){
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream(“hello.txt”));
dos.writeUTF(“我我我”);
dos.flush();
dos.writeInt(1);
dos.flush();
dos.writeBoolean(false);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(dos!=null){
dos.close();
}

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
@Test
public void test7(){
    DataInputStream dis=null;
    try {
        dis = new DataInputStream(new FileInputStream("hello.txt"));
        String name = dis.readUTF();
        int age = dis.readInt();
        boolean isMan = dis.readBoolean();
        //读取数据顺序要与写入时顺序一致
        System.out.println("name="+name);
        System.out.println("age="+age);
        System.out.println("isMan="+isMan);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (dis!=null) {
                dis.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

7、对象流的类或者接口有哪些,基本操作是什么
ObjectInputStream ObjeatOutputStream
作用:用于存储和读取基本数据类型或对象的处理流。
8、什么是序列化和反序列化。
需要让某个对象支持序列化机制
为了让某个类可序列化该类必须实现以下两个接口之一
Serializable
Externalizable
序列化:把内存中java对象转换成二进制 持久地保存在磁盘上 或通过网络进行传输
使用ObjectOutputStream
反序列化:将磁盘文件中的对象还原为内存中的一个java对象
使用ObjectInputStream
9、RandomAccessFile实现数据读写

三、nio
1、什么是NIO, NIO和传统IO有什么区别,常用的类有哪些,类的操作有哪些,请归纳
2、NIO阻塞式和非阻塞式的有什么区别
3、什么使管道,如何使用管道

四、网络编程

  1. TDP和UDP的区别
  2. 编程,分别通过TDP和UDP实现局域网通信,一端发送消息,一端成功接收消息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值