第3阶段 Java高级特性
- 字节和字符
- 第2关:字节流 - 输入输出
- 输入流
- 输出流
- 核心就是在使用完流之后,释放它所占用的资源。
- 第3关:字符流 - 输入输出
- 第4关:复制文件
- 文件和代码输入流的区别
- 第2关:ArrayList集合的增删改查
- 集合的体系结构
- 快问快答
- 第3关:集合的体系结构
- 第4关:泛型
- Map集合的特点
- Java 字符串与集合练习——词频统计
- String.split()拆分字符串
- StringTokenizer类拆分字符串
- 代码
- 第2关:确定单词在字符串中的位置
- String.indexOf(String str)
- String.indexOf(String str, int fromIndex)
- 代码
- 第3关:实现词频统计和排序输出
- 如何进行排序
字节和字符
第2关:字节流 - 输入输出
输入流
输出流
核心就是在使用完流之后,释放它所占用的资源。
OutputStream out = null;
try {
String file = "D://test.txt";
out = new FileOutputStream(file);
String str = "hello educoder";
byte[] b = str.getBytes();
out.write(b);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close(); // 释放该输出流
} catch (IOException e) {
e.printStackTrace();
}
}
}
package step2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Task {
public void task() throws IOException{
/********* Begin *********/
//使用输入流读取src/step2/input/目录下的task.txt文件信息并输出到控制台,
File file = new File("src/step2/input/task.txt");
FileInputStream fs = new FileInputStream(file);
byte[] b = new byte[8];
fs.read(b);
String str = new String(b,"UTF-8");
System.out.println(str);
//使用输出流将字符串learning practice写入到src/step2/output/目录下的output.txt,若文件目录不存在,则创建该目录。
File file2 = new File("src/step2/output");
file2.mkdir();
File file3 = new File("src/step2/output/output.txt");
file3.createNewFile();
FileOutputStream out = null;
try {
out = new FileOutputStream(file3);
String str2 = "learning practice";
byte[] b2 = str2.getBytes();
out.write(b2);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close(); // 释放该输出流
} catch (IOException e) {
e.printStackTrace();
}
}
}
/********* End *********/
}
}
第3关:字符流 - 输入输出
上面代码fw.flush()和fw.close()也可以省略fw.flush(),只写fw.close()就可以了,但是都省略是不对的,如果都省略你会发现文本没有写入到hello.txt文件。
package step3;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Task {
public void task() throws IOException{
/********* Begin *********/
String file1 = "src/step3/input/input.txt"; //创建文件
FileReader fr = new FileReader(file1); //实例化
char[] ch = new char[8]; //创建数组
fr.read(ch); //将文件的数据读入到数组中(从前到后)
String file2="src/step3/output/output.txt";//创建文件
FileWriter fw = new FileWriter(file2); // 实例化
fw.write(ch); // 读入数组中的数据到文件中(从后到前)
fr.close(); //关闭流
fw.flush(); //刷新流
fw.close(); //关闭流
/********* End *********/
}
}
字符流只适用于操作字符类型的文件.字节流来操作非字符类文件。
第4关:复制文件
package step4;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Task {
public void task() throws IOException{
/********* Begin *********/
//复制src/step4/input/目录下的input.txt文件到src/step4/output/目录下,新文件命名为output.txt;
String file1 = "src/step4/input/input.txt";
FileReader fr = new FileReader(file1);//定义FileReader读取文件
int len = 0;// 每次读取的长度
char[] cbuf = new char[1024];//每次读取数据的缓冲区
String file2 = "src/step4/output/output.txt";
FileWriter fw = new FileWriter(file2); //定义FileWriter写文件
while((len = fr.read(cbuf)) != -1){
fw.write(cbuf,0,len);//将cbuf 0 到len长度的数据添加到builder
}
fw.close(); //释放资源 刷新缓冲区
fr.close();
//字符流只适用于操作字符类型的文件.字节流来操作非字符类文件。
//复制src/step4/input/目录下的input.jpg文件到src/step4/input/目录下,新文件命名为output.jpg
//定义文件输入流读取文件信息
FileInputStream fs = new FileInputStream("src/step4/input/input.jpg");
//定义文件输出流写文件
FileOutputStream fos = new FileOutputStream("src/step4/output/output.jpg");
int len2 = 0; //每次读取数据的长度
byte[] bys = new byte[1024]; //数据缓冲区
while( (len2 = fs.read(bys)) != -1){
fos.write(bys, 0, len2);
}
//释放资源 刷新缓冲区
fs.close();
fos.close();
/********* End *********/
}
}
文件和代码输入流的区别
文件
FileReader fr = new FileReader(file1);
FileWriter fw = new FileWriter(file2); // 实例化
图片
FileInputStream fs = new FileInputStream("src/step4/input/input.jpg");
FileOutputStream fos = new FileOutputStream("src/step4/output/output.jpg");
相同点
都需要释放资源
1、//释放资源 刷新缓冲区
fs.close();
fos.close();
2、fr.close(); //关闭流
fw.flush(); //刷新流
fw.close(); //关闭流
第2关:ArrayList集合的增删改查
package step2;
import java.util.ArrayList;
import java.util.Scanner;
public class HelloWorld {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
//获取输入的数据并添加至集合
Scanner sc = new Scanner(System.in);
ArrayList list = new ArrayList<>();
int length = sc.nextInt();
for(int i =0 ; i< length; i++){
list.add(sc.next());
}
//System.out.println(list.toString());
/********** Begin *********/
//String name = (String)list.get(0); 集合的get()方法获取到数据
//获取数组的长度
int l=list.size();
//System.out.println("集合长度:"+l);
//删除集合的第一个和最后一个元素;
list.remove(length-1);
list.remove(0);
//System.out.println("删除后集合:"+list.toString());
//添加两个字符串:hello,educoder至集合中;
list.add("hello");
list.add("educoder");
//System.out.println("加入元素后集合:"+list.toString());
//修改集合的第三个元素,改为:list;
list.set(2,"list");
//输出集合中所有的元素。
for(int j=0; j<list.size(); j++){
System.out.println((String)list.get(j));
}
/********** End **********/
}
}
集合arraylist 输出时需要用 list.get()
集合的体系结构
Java中的集合分为两大家族,一个是Collection家族,Collection家族有三大成员:List、Queue、Set,这三大成员有三个子类(实际还有很多,这里不一一列举)分别是,ArrayList,LinkedList,HashSet,这个家族有一个特点,那就是他们都是单身,集合中的元素都是独立存在的。
另一个就是Map家族了,这个家族的特点就是他们都是成双成对(key和value)一起出现的
快问快答
问:Set集合与List集合有什么区别呢?
答:Set集合中的数据不可重复,数据是无序的,List集合的数据可以重复,数据是有序的。
问:就没啦?[严肃脸]
答:哦哦,还有,Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变,List和数组类似
,可以动态增长,根据实际存储的数据的长度自动增长List的长度。查找元素效率高,插入删除效率低,
因为会引起其他元素位置改变。
问:Map集合中的元素可以重复吗?
答:不可以!
问:你说一说,LinkedList和ArrayList的区别吧。
答:好嘞,LinkedList集合增删速度更快,ArrayList改查更快。
问:咳咳咳,下一位!
答:诶诶诶,别呀,我还没说完呢:
ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。LinkedList是双向链表。
对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
第3关:集合的体系结构
package step3;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
public class HelloWorld {
public HashSet getHashSet(){
/********** Begin **********/
HashSet set = new HashSet();
set.add("www.educoder.net");
return set;
/********** End **********/
}
public ArrayList getArrayList(){
/********** Begin **********/
List list = new ArrayList();
list.add("www.educoder.net");
return list;
/********** End **********/
}
public LinkedList getLinkedList(){
/********** Begin **********/
LinkedList list1 = new LinkedList();
list1.add("www.educoder.net");
return list1;
/********** End **********/
}
public Map getHashMap(){
/********** Begin **********/
HashMap map = new HashMap();
map.put("address","www.educoder.net");
return map;
//error: Map is abstract; cannot be instantiated
//要用HashMap不能用父类Map
/********** End **********/
}
}
Collection家族用add添加元素,Map家族用put
第4关:泛型
其实泛型也是一样,只不过在这里泛型用在集合上,即指定集合中只能放某一种类型的元素。
ex:你要往ATM机中存钱,就只能放毛爷爷,而不能放冥币,这就是泛型,指定只能用一种类型。
package step4;
import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//程序会输入三次数据
/********** Begin **********/
//创建一个只能存储String类型数据的List集合;
List<String> list = new ArrayList<String>();
//将程序输入的数据存入List集合中;
for(int j=0;j<3;j++){
list.add(sc.nextLine());
}
//输出集合中所有的数据。
for(int i=0; i<list.size(); i++){
System.out.println("集合的第"+(i+1)+"个数据为:"+list.get(i));
}
/********** End **********/
}
}
Map集合的特点
有三点需要你记住:
Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够根据key快速查找value;
键(key)值不可重复,值(value)是可以的,通过key可以查找value;
Map支持泛型,形式如:Map<K,V>。
2.删除、修改和获取数据。
Map<String,String> map = new HashMap<String,String>();
map.put("name","张三");
map.put("sex","男");
System.out.println("姓名:" + map.get("name") + "性别:" + map.get("sex"));
//修改数据 使用 map.put(key) 方法
map.put("name","李四");//因为key不能重复,所以修改数据和添加数据使用的同一个方法
System.out.println("姓名:" + map.get("name") + "性别:" + map.get("sex"));
//删除数据 使用 map.remove(key)方法
map.remove("name");
System.out.println(map.toString());//map.toString方法可以直接输出map集合中的数据
map.get(“name”)输出key = name时对应的value
package step5;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class HelloWorld {
public static void main(String[] args) {
Map<String, Integer> menuDict = new HashMap<>();
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 5; i++) {
menuDict.put(sc.next(),sc.nextInt());
}
/********** Begin **********/
//向menuDict集合中添加一道菜名lamb,它的价格是50;
menuDict.put("lamb",50);
//获取menuDict集合中的fish的价格并打印出来;
System.out.println(menuDict.get("fish"));
//将menuDict集合中的fish的价格改为100;
menuDict.put("fish",100);
//删除menuDict集合中noodles这道菜;
menuDict.remove("noodles");
//输出新的menuDict菜单。
System.out.println(menuDict.toString());
/********** End **********/
}
}
/因为key不能重复,所以修改数据和添加数据使用的同一个方法
Java 字符串与集合练习——词频统计
String.split()拆分字符串
public class SplitDemo {
public static void main(String[] args) {
String Str="Harry James Potter";
String[] StrArray=Str.split("\\s");//"\\s"表示空格
//也可以来" "来进行拆分 String[] StrArray=Str.split(" ");
for(String str:StrArray){
System.out.println(str);
}
}
StringTokenizer类拆分字符串
import java.util.StringTokenizer;
public class StringTokenDemo {
public static void main(String[] args) {
String Str="Harry James Potter";
StringTokenizer strToken=new StringTokenizer(Str);
//当有拆分的子字符串时,输出这个字符串
while(strToken.hasMoreTokens()){
System.out.println(strToken.nextToken());
}
}
}
代码
package step1;
import java.util.List;
import java.util.ArrayList;
import java.util.StringTokenizer;
public class StudentDemo{
//使用String.split()方法分割
public List<String> splitPartition(String str){
List<String> list=new ArrayList<String>();
//请在此添加实现代码
/********** Begin **********/
String[] StrArray=str.split("\\|");// "\\"不能少
//也可以来" "来进行拆分 String[] StrArray=Str.split(" ");
for(String str1:StrArray){
list.add(str1);
}
/********** End **********/
return list;
}
//使用StringTokenizer类进行分割
public List<String> tokenPartition(String str){
List<String> list=new ArrayList<String>();
//请在此添加实现代码
/********** Begin **********/
//将字符串按?分隔开,删除?用false。保留分隔符用True
StringTokenizer strToken=new StringTokenizer(str,"?",false);
//StringTokenizer是字符串分隔解析类型,属于:java.util包。
//当有拆分的子字符串时,输出这个字符串
while(strToken.hasMoreTokens()){
list.add(strToken.nextToken());
}
/********** End **********/
return list;
}
}
第2关:确定单词在字符串中的位置
String.indexOf(String str)
返回指定子字符串在此字符串中第一次出现处的索引。(若返回-1则表示在该字符串中没有你要找的单词)
//声明一段字符串
String str="Can I help you";
//显示“I”在str中第一次出现的下标
System.out.println(str.indexOf("I"));
//String.indexOf(int ch)方法与此方法形同,只是参数是单个字符的ASCII码 (含空格)
String.indexOf(String str, int fromIndex)
返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
String str="Can I help you";
System.out.println(str.indexOf("I",5));
//同样String.indexOf(int ch, int fromIndex)方法与此方法也形同,只是参数是单个字符的ASCII码
输出:-1
代码
package step2;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.StringTokenizer;
public class StudentDemo{
//返回一个Map集合来得到单词和首次出现的下标 key为单词名称 value为单词的角标
public Map<String, Integer> getMap(String str){
Map<String, Integer> map = new HashMap<String, Integer>();
//对str进行分割 再加入map集合中
//请在此添加实现代码
/********** Begin **********/
List<String> list=new ArrayList<String>();
StringTokenizer strToken=new StringTokenizer(str," .?,!:",false);
//StringTokenizer是字符串分隔解析类型,属于:java.util包。
//当有拆分的子字符串时,输出这个字符串
while(strToken.hasMoreTokens()){
list.add(strToken.nextToken());
}
for(int i=0; i<list.size(); i++){
String key = list.get(i);
int value = str.indexOf(key);
map.put(key,value);
}
/********** End **********/
return map;
}
}
**❥split不行
第3关:实现词频统计和排序输出
package step3;
import java.util.Map;
import java.util.HashMap;
import java.util.StringTokenizer;
public class StudentDemo{
//获取单词的数量
public Map<String, Integer> getWordCount(String str) {
Map<String, Integer> map = new HashMap<String, Integer>();
//请在此添加实现代码
/********** Begin **********/
//将指定文本(可以通过右侧文件目录下的src/step3/readme.txt查看)以降序的方式输出每个单词出现的次数。
//分词存储
StringTokenizer strToken=new StringTokenizer(str," ,?.!:;\"\"‘’\n",false);
//StringTokenizer是字符串分隔解析类型,属于:java.util包。
//当有拆分的子字符串时,输出这个字符串
int count;
String word;
while(strToken.hasMoreTokens()){
word = strToken.nextToken();
if(map.containsKey(word)){
//拿到之前存在map集合中该单词的次数
count=map.get(word);
map.put(word, count+1);
}else{
map.put(word, 1);
}
}
/********** End **********/
return map;
}
}
如何进行排序
使用Collections包装类。它包含有各种有关集合操作的静态多态方法。
//可根据指定比较器产生的顺序对指定列表进行排序。
Collections.sort(List list, Comparator<? super T> c)
//以上实例中的map集合为例 将map集合的每一项添加进list集合中
List<Map.Entry<String, Integer>> infos = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(infos, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> o1,
Map.Entry<String, Integer> o2) {
//前者-后者 升序 后者-前者 降序
return (o2.getValue() - o1.getValue());
}
});