首页 > 代码库 > 黑马程序员-入学笔试题
黑马程序员-入学笔试题
笔试结束,列一下笔试题和我的解答,最后得分29.7。
1、 编写一个类,在main方法中定义一个Map对象(采用泛型),加入若干个对象,然后遍历并打印出各元素的key和value。
package com.itheima; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class Test1 { public static void main(String[] args) { //定义一个key值为String类型,value值为Integer类型的Map集合,可用于存储一段话中各个单词出现次数信息 TreeMap<String,Integer> tm=new TreeMap<String,Integer>(); tm.put("hello", 2); tm.put("you", 8); tm.put("are", 4); tm.put("do", 6); //第一种方式遍历TreeMap元素:keySet Set<String> kSet=tm.keySet(); Iterator<String> it=kSet.iterator(); while(it.hasNext()){ String str=it.next(); Integer val=tm.get(str); System.out.println(str+" : "+val); } System.out.println("============================"); //第二种方式遍历TreeMap元素:EntrySet Set<Map.Entry<String, Integer>> eSet=tm.entrySet(); Iterator<Map.Entry<String,Integer>> itor=eSet.iterator(); while(itor.hasNext()){ Map.Entry<String, Integer> me=itor.next(); String s=me.getKey(); Integer v=me.getValue(); System.out.println(s+" : "+v); } } }
2、 有五个学生,每个学生有3门课(语文、数学、英语)的成绩,写一个程序接收从键盘输入学生的信息,输入格式为:name,30,30,30(姓名,三门课成绩),然后把输入的学生信息按总分从高到低的顺序写入到一个名称"stu.txt"文件中。要求:stu.txt文件的格式要比较直观,打开这个文件,就可以很清楚的看到学生的信息。
package com.itheima; /* * 思路:1. 定义Student对象,让其自身具备比较性,同时复写toString方法,方便后面写入文件 * 2. 将键盘输入封装成字符缓冲流,按行读取,每一行字符串封装成一个Student对象 * 3. 将Student对象放到TreeSet集合中,实现按序存储 * 4. 将TreeSet集合中的各个Student对象写入到stu.txt文件中 */ import java.io.*; import java.util.Iterator; import java.util.TreeSet; public class Test2 { public static void main(String[] args) throws Exception { BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw=new BufferedWriter(new FileWriter("stu.txt")); TreeSet<Student> ts=new TreeSet<Student>(); String line=null; System.out.println("请输入学生信息,格式如name,30,30,30:"); //将从键盘接收到学生信息放到一个TreeSet集合中 while((line=bufr.readLine())!=null){ if("over".equals(line)) break; String[] strs=line.split(","); if(strs.length!=4){ System.out.println("输入信息格式不对,请重新输入"); continue; } ts.add(fillStu(strs)); } bufr.close(); //将TreeSet写入到stu.txt文件中 Iterator<Student> it=ts.iterator(); while(it.hasNext()){ Student stu=it.next(); bufw.write(stu.toString()); bufw.newLine(); } bufw.flush(); bufw.close(); } //根据一个字符串数组信息填充生成Student对象 public static Student fillStu(String[] strs){ Student stu=new Student(strs[0],Float.parseFloat(strs[1]),Float.parseFloat(strs[2]),Float.parseFloat(strs[3])); return stu; } } //定义Student类,实现带泛型的Comparable接口,让Student对象自身具备比较性 class Student implements Comparable<Student>{ private String name; private float yuWen; private float shuXue; private float yingYu; private float sum; public Student(String name, float yuWen, float shuXue, float yingYu) { super(); this.name = name; this.yuWen = yuWen; this.shuXue = shuXue; this.yingYu = yingYu; this.sum=yuWen+shuXue+yingYu; } @Override //复写compareTo()方法,实现Student对象按总分比较,总分一致时按姓名比较 public int compareTo(Student o) { float result=this.sum-o.sum; if(result>0) return -1; else if(result==0){ return this.name.compareTo(o.name); } return 1; } public String toString(){ return name+", 语文成绩:"+yuWen+" 数学成绩:"+shuXue+" 英语成绩:"+yingYu+" ---- 总分:"+sum; } }
3、 自定义枚举 Week 用于表示星期,Mon,Tue,Wed...要求每个枚举值都有toLocaleString 方法,用于获得枚举所表示的星期的中文格式 星期一、星期二、星期三...
package com.itheima; public class Test3{ public static void main(String[] args){ //测试实现的enum枚举,枚举对象的中文格式是否可以正常显示 Week wed=Week.Wed; System.out.println(wed.toLocalString()); } } enum Week { //定义Mon,Tue,Wed...等枚举对象,使用内部类形式实现抽象方法 Mon { public String toLocalString() { return "星期一"; } }, Tue { public String toLocalString() { return "星期二"; } }, Wed { public String toLocalString() { return "星期三"; } }, Thu { public String toLocalString() { return "星期四"; } }, Fri { @Override public String toLocalString() { return "星期五"; } }, Sat { public String toLocalString() { return "星期六"; } }, Sun { public String toLocalString() { return "星期天"; } }; //定义枚举类的抽象方法 public abstract String toLocalString(); }
4、 请说明Java中字符‘\‘的含义,有什么作用?
package com.itheima; /* * 答:1.'\'可以转义字符,将其后面紧跟的字母或符号转换成其它的含义。 * 常用的转义字符有:\n:换行,\b:退格,\r:按下回车键,\t:制表符,相当于tab键。 * 2. 因为'\'会转义后面的字符,所以代码中如果要保持\原先的意思,需要在 \前面再加一个\,表示后面的\保持原形,不转义 */
5、 将字符串中进行反转。abcde --> edcba
package com.itheima; /* * 思路:将待转换的字符串先转换成字符数组,对字符数组进行首尾互换,即实现了反转,再将首尾互换后的字符数组封装成字符串返回 */ public class Test5 { public static void main(String[] args) { String str="abcdefghi"; System.out.println(rev(str)); } public static String rev(String str){ //将字符串转换成字符数组 char[] chs=str.toCharArray(); int len=str.length(); char temp; //实现字符数组首尾互换 for(int i=0;i<len/2;i++){ temp=chs[i]; chs[i]=chs[len-1-i]; chs[len-1-i]=temp; } //字符数组封装成字符串返回 return new String(chs); } }
6、 分析以下程序运行结果,说明原理。(没有分析结果不得分)。---下面直接分析给出的代码,原题中只有代码,没有任何注释。
package com.itheima; //分析如下: public class Test6 { public static void main(String args[]) { MyThread t = new MyThread(); //仅调用t.run()并没有启动线程,只是普通的函数调用 t.run(); //t线程启动,开始在一个与主线程不同的线程分支运行run方法中的代码,t线程与主线程抢夺CPU资源 //run方法一开始就休眠,所以主线程抢到CPU时间,开始运行下面的System.out.println("A") t.start(); System.out.println("A"); } } class MyThread extends Thread { public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { } //休眠结束运行下面的语句 System.out.println("B"); } } /* 程序运行结果是 B A B 运行结果分析: 1. JVM启动后,从main函数入口,开始执行,并创建main主线程 2. 主线程创建MyThread对象t,但t所代表的线程还没有启动 3. 主线程调用线程对象t的run()方法,这时还是没有启动t线程,只是普通的函数调用,所以程序会sleep 3秒,然后打印B 4. 主线程调用t.start(),t线程被启动,开始有一个线程分支在运行,分支中运行的是t.run中的代码,而main主线程仍在main函数中往下执行 5. t线程分支和main主线程开始抢夺CPU时间,因为t线程分支中run方法中一开始就sleep 3秒,所以主线程轻而易举地抢到执行权,继续往下执行, 6. main函数的下一条语句是打印A,所以输出A,这时,main主线程执行完毕 7. 主线程完毕后,t线程分支还没休眠结束,所以console控制台应该会停顿差不多3秒的时间,然后t线程中接着执行run方法中的剩余语句,打印B. */
7、 有一个类为ClassA,有一个类为ClassB,在ClassB中有一个方法b,此方法抛出异常,在ClassA类中有一个方法a,请在这个方法中调用b,然后抛出异常。在客户端有一个类为TestC,有一个方法为c ,请在这个方法中捕捉异常的信息。完成这个例子,请说出java中针对异常的处理机制。
package com.itheima; /* * 思路:将一个int型值转换成ASCII码字符,如果int值超过了127,抛出异常,用这个例子来切合题目并说明java异常处理机制 */ public class Test7 { public static void main(String[] args) { c(); } //c()方法中调用A类的a()方法,OutASCIIException异常没必要再抛给更上层调用者,直接在c()方法中捕获并处理 public static void c(){ A clsA=new A(); try { clsA.a(); System.out.println("异常抛出点之后的try块的语句不执行。。。"); } catch (OutASCIIException e) { System.out.println(e.toString()); System.out.println("错误的数值 是:"+e.getVal()); } } } //A类中的a()方法调用B类的b(int)方法,对异常不做处理,直接在函数声明中抛出,让上层调用者处理 class A{ public void a() throws OutASCIIException { B clsB=new B(); char d=clsB.b(145); } } //B类,其中的b方法实现int值到ASCII字符的转换,可能抛出自定义异常OutASCIIException class B{ public char b(int a) throws OutASCIIException{ if(a>127) throw new OutASCIIException("超出了ASCII码值的范围,转换成字符失败:",a); return (char)a; } } //自定义异常,将一个int型值转换成ASCII字符,当要转换的int值超过ASCII码取值范围时,抛出异常 class OutASCIIException extends Exception { int val; OutASCIIException(String msg, int val){ super(msg); this.val=val; } int getVal(){ return val; } } /* * java异常处理机制: * java通过类的形式来描述异常,将异常封装成对象。 * java异常体系根节点是Throwable类,它描述了异常的共性(异常信息,引发异常的原因,可抛性等)。 * java提供2种处理异常的方式: * 1. 用try...catch...finally语句处理 * try中存放可能出现异常的代码,try块中异常抛出点之后的语句不会再执行; * catch捕获异常并进行异常处理;finall中存放一定会执行的代码,不管异常有没有发生。 * 2. 在函数上用throws声明该函数可能出现的异常类,让函数的调用者去处理该异常 调用者捕获该异常后,可以继续向上throws异常,直到抛给jvm,也可以用try...catch处理。 */
8、 定义一个文件输入流,调用read(byte[] b)方法将exercise.txt文件中的所有内容打印出来(byte数组的大小限制为5)。
package com.itheima; /* * 思路:因为缓冲区数组固定是5个字节大小,而当文件中汉字时,汉字占2个字节,一次读取5个字节可能出现截取半个汉字的情况,所以不能急着打印; * 先分析一次读取后是否截取到了半个汉字,如果是,只打印前4个字节的内容,然后退回一个字节再读取,如果不是,直接输出; * 由此想到了利用随机访问文件流,可以设置当前指针位置,必要时回退一个字节。 */ import java.io.FileInputStream; import java.io.RandomAccessFile; public class Test8 { public static void main(String[] args) throws Exception { RandomAccessFile raf=new RandomAccessFile("exercise.txt","r"); byte[] buf=new byte[5]; int len=0; int currentPos=0; while((len=raf.read(buf))!=-1){ String str=new String(buf,0,len); currentPos=currentPos+len; int i=0; //i表示一个ASCII字符字节位置或一个汉字的第一个字节位置,汉字GBK编码的第一个字节都小于0 while(i<5){ if(buf[i]<0) i=i+2; else i=i+1; } //read(buf)后,如果截取到了半个汉字,那buf[4]肯定是一个汉字的第一个字节,buf[4]<0,上面的i=6 if(i==6){ //截取了半个汉字时,应该退回到前一个位置,重新再读取5个字节 currentPos=currentPos-1; raf.seek(currentPos); //只把前4个字节的内容打印出来 System.out.print(str.substring(0,str.length()-1)); }else{ //截取到完整汉字,整个输出 System.out.print(str); } } } }
9、 写一方法,打印等长的二维数组,要求从1开始的自然数由方阵的最外圈向内螺旋方式地顺序排列。 如: n = 4 则打印:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
package com.itheima; /* * 思路:1. 按螺旋的圈数进行循环,对于n阶方阵,螺旋圈数是(n+1)/2. * 2. 每一圈都是按顺时针走,顺时针位置上的值依次增加,可以先循环列出向右增长的横行和向下增长的竖列的值,剩下的半圈的值可利用对称性得到。 * 3. 里面一圈的起始值是它外面一圈左侧位置上的值加1 */ public class Test9 { public static void main(String[] args) { xzArray(8); } public static void xzArray(int n){ int[][] arr=new int[n][n]; //如果每一圈开头位置相邻左侧位置的值为start,那每一圈开头的值就是start+1,最外面一圈的start值设置为0 int start=0; //按螺旋的圈数进行循环,给定n值的方阵,其螺旋的圈数(n+1)/2 for(int q=0;q<(n+1)/2;q++){ //除第一圈外,从外向里,每一圈的开头起始值是其左侧紧邻位置的值+1,即start+1 if(q!=0){ start=arr[q][q-1]; } //获取每一圈往右增长的一行和往下增长的一列的值,每一圈的元素个数是随着圈从外向内的层次数而变化的,用j表示,i代表每一圈向右的一行相对起始值的偏移 for(int j=q,i=0;j<n-q&&i<=j;j++,i++){ arr[q][j]=start+i+1; //圈子越向内时,每行或每列的元素个数会减少,所以转折的越快 arr[j][n-1-q]=start+i+n-2*q; } //获得每一圈往右增长的一行和往下增长的一列的值,向左增长的行数据和向上增长的列数据分别利用对称特性行到,每对对称位置的两个元素加起来的值都是该层最右下角元素值的2倍。 for(int i=q+1;i<n-q;i++){ arr[i][q]=2*arr[n-1-q][n-1-q]-arr[q][i]; arr[n-1-q][i]=2*arr[n-1-q][n-1-q]-arr[i][n-1-q]; } } printArray(arr); } //打印数组的函数 public static void printArray(int[][] arr){ for(int i=0;i<arr.length;i++){ for(int j=0;j<arr[i].length;j++){ //printf实现格式化打印 System.out.printf("%4d",arr[i][j]); } System.out.println(); } } }
10、 金额转换,阿拉伯数字转换成中国传统形式。
例如:101000001010 转换为 壹仟零壹拾亿零壹仟零壹拾圆整
package com.itheima; /* * 思路:1. 先试图将普通的4位数及4位数以下的金额转换成传统汉字形式 * 2. 任一长串金额,可以以4位为一组进行分组,分组内金额的转换形式与普通单独的4位数金额一致,分组外,每个分组整合有不同的单位 * 3. 程序可以转换整数部分长达16位的金额,最高单位是万亿,再向上的单位暂时没有理清,后面有机会会补充 * 4. 考虑带小数点的金额,转换方法类似,相对整数部分摊简单一些,小数可以精确到小数点后3位数,3位以后的小数没有可用的单位,不考虑 * 5. 阿拉伯数字与汉字大写之间的转换利用查表法实现 * */ public class Test10 { public static void main(String[] args) { String str="400100001010.098"; //String str="0100"; //System.out.println(four2Ch(str)); num2Ch(str); } public static void num2Ch(String str){ String[] strs=str.split("\\."); int len=strs[0].length(); StringBuilder strBuilder=new StringBuilder(); StringBuilder strB=new StringBuilder(); String[] bigTable={"圆","万","亿","万亿"}; int n=0; //以4位为一组,先不带单位转换该组为汉字形式,然后每组再加上对应的"圆","万","亿","万亿"单位 while(len>0){ int start=(len-4)>0?len-4:0; strB=four2Ch(strs[0].substring(start, len)); strBuilder.insert(0,strB); if(strB.length()==0){ //有多个连续的零时只显示一个 if(!strBuilder.toString().startsWith("零")){ strBuilder.insert(strB.length(),"零"); } }else{ strBuilder.insert(strB.length(),bigTable[n]); } n++; len=len-4; } if(strs.length>1){ strBuilder.append(point2Ch(strs[1])); }else{ strBuilder.append("整"); } System.out.println(strBuilder.toString()); } //将一个任意4位以内的数转换成中国传统货币形式 public static StringBuilder four2Ch(String str){ StringBuilder strB=new StringBuilder(); String[] numTable={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"}; String[] unitTable={"","拾","百","仟"}; int len=str.length(); char[] chArr=str.toCharArray(); for(int i=len-1;i>=0;i--){ //某一位上为0是,不显示该位的单位 if(chArr[i]=='0'){ //结尾处的0不转换,直接去掉,除结尾外,其余位置有连续的多个零时,只保留一个零 if(i!=len-1&&chArr[i+1]!='0') strB.append("零"); } //该位上值不为0时,转换该值为汉字形式,并显示其单位 else{ strB.append(unitTable[len-1-i]); strB.append(numTable[chArr[i]-48]); } } return strB.reverse(); } //将小数转换成角、分、厘形式 public static StringBuilder point2Ch(String str){ StringBuilder strP=new StringBuilder(); String[] pnumTable={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"}; String[] punitTable={"角","分","厘"}; int len=str.length(); char[] chArr=str.toCharArray(); for(int i=0;i<len;i++){ if(chArr[i]=='0'){ if(i!=len-1&&chArr[i+1]!='0') strP.append("零"); }else{ strP.append(pnumTable[chArr[i]-48]); strP.append(punitTable[i]); } } return strP; } }