最近面试了几家公司,发现大部分公司面试题有相似的地方。现在此记录下我还记得的一些题:
JAVA部分:
1.Java Map 按Key排序和按Value排序:
参考链接:Java Map 按Key排序和按Value排序
2.从一个文件中统计每个单词的次数,排序输出:
package com.test.string; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * java实现读取英文文章,统计其中每个单词出现的次数并输出 * @author halbert * */ public class FileWordCount { public void count() throws IOException{ BufferedReader reader = new BufferedReader(new FileReader("D:\\test\\english.txt")); StringBuffer buffer = new StringBuffer(); String line = null; while( (line = reader.readLine()) != null ){ buffer.append(line); } reader.close(); Pattern expression = Pattern.compile("[a-zA-Z]+"); //定义正则表达式匹配单词 String string = buffer.toString(); Matcher matcher = expression.matcher(string); Mapmap = new TreeMap (); String word = ""; int n = 0; Integer times = 0; while(matcher.find()){ //是否匹配单词 word = matcher.group(); //得到一个单词,树映射中的键 n++; if( map.containsKey(word) ){ //如果该键存在,则表示单词出现过 times = map.get(word); //得到单词出现的次数 map.put(word, times+1); } else { map.put(word, 1); //否则单词是第一次出现,直接放入map } } List > list = new ArrayList >(map.entrySet()); Comparator > comparator = new Comparator >(){ @Override public int compare(Entry left, Entry right) { return (left.getValue()).compareTo(right.getValue()); } }; Collections.sort(list, comparator); System.out.println("统计分析如下:"); System.out.println("t 文章中单词总数" + n + "个"); System.out.println("具体的信息在原文件目录的result.txt文件中"); BufferedWriter bufw = new BufferedWriter(new FileWriter("D:\\test\\result.txt")); for(Entry me : list){ bufw.write(me+""); bufw.newLine(); } bufw.write("english.txt中的单词总数" + n + "个"); bufw.newLine(); bufw.write("english.txt中不同单词" + map.size() + "个"); bufw.close(); } public static void main(String[] args) { try { FileWordCount fwc = new FileWordCount(); fwc.count(); } catch (IOException e) { e.printStackTrace(); } } }
参考链接:java程序员的从0到1:统计某字符串在某文件中出现的次数(面试题)
3.手写arraylist:
参考链接:java面试题答疑(手写arraylist、进制转换、多线程、动态代理)
4.手写一把可重入锁:
public class MyLock implements Lock { private boolean isLocked = false; //定义一个变量,标记锁是否被使用 private Thread runningThread = null; //第一次线程进来的时候,正在运行的线程为null private int count = 0; //计数器 @Override public synchronized void lock() { Thread currentThread = Thread.currentThread(); //不断的重复判断,isLocked是否被使用,如果已经被占用,则让新进来想尝试获取锁的线程等待,直到被正在运行的线程唤醒 //除了判断当前锁是否被占用之外,还要判断正在占用该锁的是不是本线程自己 while(isLocked && currentThread != runningThread) { //如果锁已经被占用,而占用者又是自己,则不进入while循环 try { wait(); }catch (InterruptedException e) { e.printStackTrace(); } } //进入该代码块有三种情况: // 1.第一个线程进来,此时isLocked变量的值为false,线程没有进入while循环体里面 // 2.线程进入那个循环体里面,调用了wait()方法并经历了等待阶段,现在已经被另一个线程唤醒, // 3.线程不是第一次进来,但是新进来的线程就是正在运行的线程,则直接来到这个代码块 // 唤醒它的线程将那个变量isLocked设置为true,该线程才跳出了while循环体 //跳出while循环体,本线程做的第一件事就是赶紧占用线程,并告诉其他线程说:嘿,哥们,我占用了,你必须等待,计数器+1,并设置runningThread的值 isLocked = true; //将isLocked变量设置为true,表示本线程已经占用 runningThread = currentThread; //给正在运行的线程变量赋值 count++; //计数器自增 } @Override public void lockInterruptibly() throws InterruptedException { } @Override public boolean tryLock() { return false; } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { return false; } @Override public synchronized void unlock() { //线程释放锁,释放锁的过程分为三步 //1. 判断发出释放锁的请求是否是当前线程 //2. 判断计数器是否归零,也就是说,判断本线程自己进来了多少次,是不是全释放锁了 //3. 还原标志变量 if(runningThread == Thread.currentThread()) { count--;//计数器自减 if(count == 0) { //判断是否归零 isLocked = false; //将锁的状态标志为未占用 runningThread = null; //既然已经真正释放了锁,正在运行的线程则为null notifyAll(); //通知所有等待的线程,谁抢到我不管 } } } @Override public Condition newCondition() { return null; } } --------------------- 作者:SpringChang 来源:CSDN 原文:https://blog.csdn.net/zhang5476499/article/details/83794711 版权声明:本文为博主原创文章,转载请附上博文链接!
参考链接:Java并发编程:自己动手写一把可重入锁
5.说几个JAVA中的单例模式,然后你最喜欢用哪个?为什么?
饿汉式和懒汉式。
//第一种形式: 饿汉式单例类 //饿汉式单例类.在类初始化时,已经自行实例化 public class Singleton { private Singleton(){} private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } } //第二种形式:懒汉式单例类 public class Singleton { private Singleton(){} private static Singleton instance = null; public static synchronized Singleton getInstance() { if (instance==null)instance=new Singleton(); return instance; } }
第一种形式要更加安全些
instance = new Singleton();
static属于类的资源,类资源在jvm加载类的时候就加载好了,instance一直引用这new Singleton(),所以永远都不会释放一直存在与内存中直到程序结束运行;
第2种的话如果两个线程同一时刻去访问getInstance的时候就可能创建两个实例,所以不安全;
解决办法(加上同步锁)。
参考链接:快速理解Java中的五种单例模式
6.说说你对Java中的栈内存和堆内存的看法:
参考链接:JAVA面试、进阶必备——堆内存与栈内存
7.http在传输时是无状态的,你是如何解决的:
可以使用Cookie来解决无状态的问题,Cookie就相当于一个通行证,第一次访问的时候给客户端发送一个Cookie,当客户端再次来的时候,拿着Cookie(通行证),那么服务器就知道这个是”老用户“。
参考链接:Java面试之http知识点(必问) HTTP面试题都在这里
8.设计一个秒杀系统
参考链接:如何设计一个秒杀系统 秒杀系统设计(JAVA)
9.设计一个大数据高并发系统
秒杀系统和高并发系统均有视频,百度云链接:
链接: https://pan.baidu.com/s/1ooQaputdmsoHm9qT-PyXRw 提取码: 686e
.NET部分:
其实C#和Java中大部分语法类似,故就算只想走Java部分题也有参考价值。
1.面向对象的三个特性,请简述。
封装:将对象中的方法,属性隐藏起来。外届程序调用对象的方法,只能通过对象提供给外部的接口来调用。这样可以可以让人忽略代码的具体细节实现,使代码更易维护。同时因为不能直接调用、修改对象内部的私有属性,在一定程度上保证了系统安全性。
继承:主要用于代码复用,将多次使用的公共代码提取出来,以达到提高编码效率目的。
多态:所谓的多态是指在继承体系中,所有派生类都从基类继承接口,但由于每个派生类都是独立的实体,因此在接收同一消息的时候,可能会生成不同的响应。多态的作用作为隐藏代码实现细节,使得代码能够模块化;扩展代码模块,实现接口重用。
2.用.net做B/S结构的系统,您是用几层结构来开发,每一层之间的关系以及为什么要这样分层?
三层。从下至上分别为:数据访问层、业务逻辑层(又或成为领域层)、表示层;
数据访问层:有时候也称为是持久层,其功能主要是负责数据库的增删查改操作;
业务逻辑层:是整个系统的核心,它与这个系统的业务(领域)有关
表示层:是系统的UI部分,负责使用者与整个系统的交互。
优点: 分工明确,条理清晰,易于调试,而且具有可扩展性。
缺点: 增加成本。
3.列举ASP.NET 页面之间传递值的几种方式。
有页面传值、存储对象传值、ajax、类、model、表单等。但是一般来说,常用的较简单有QueryString,Session,Cookies,Application,Server.Transfer。
QueryString 传递一个或多个安全性要求不高或是结构简单的数值。但是对于传递数组或对象的话,就不能用这个方法了
session(viewstate) 简单,但易丢失 作用于用户个人,过量的存储会导致服务器内存资源的耗尽。
application 对象的作用范围是整个全局,也就是说对所有用户都有效。其常用的方法用Lock和UnLock
cookie 简单,但可能不支持,可能被伪造 Cookie是存放在客户端的,而session是存放在服务器端的。而且Cookie的使用要配合ASP.NET内置对象Request来使用 input ttype="hidden" 简单,可能被伪造 url参数简单,显示于地址栏,长度有限
Server.Transfer 把流程从当前页面引导到另一个页面中,新的页面使用前一个页面的应答流 数据库稳定,安全,但性能相对弱
参考链接:ASP.NET页面之间传递值的几种方式
4.事件和委托的区别
事件是委托的封装,可以理解为一种特殊的委托。
事件里面其实就两个方法(即add_event()和remove_event())和一个私有的委托变量,这两个方法里面分别是对这个私有的委托变量进行的合并和移除,当调用事件的+=时其实是调用的事件里面的add_event()方法,同样-=调用的是remove_event()方法。
事件只能够从对象外部增加新的响应方法和删除已知的响应方法,而不能主动去触发事件和获取其他注册的响应方法等信息。如果使用公有的delegate则不能做这些限制,也就是说事件对委托做了限制,使委托使用起来更加方便。也有人说事件是对委托的阉割,大概也是这个意思。
5.C#中的接口和类有什么异同
异:
不能直接实例化接口。
接口不包含方法的实现。
接口、类和结构可从多个接口继承。但是C# 只支持单继承:类只能从一个基类继承实现。
类定义可在不同的源文件之间进行拆分。
同:
接口、类和结构可从多个接口继承。
接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
接口可以包含事件、索引器、方法和属性。
一个类可以实现多个接口。
6.SQL注入是什么意思以及防止SQL注入:
参考链接:sql注入是什么意思以及防止sql注入?
SQL:
1. 取出表A中第31到第40记录:
1、假设ID是连续的:
select top 10 * from A where ID not in (select top 30 ID from A)
或
select * from A where ID between 31 and 40
2、假设ID是不连续的:
select top 40 * from A except select top 30 * from A
或
select top 10 * from A where ID > (select max(ID) from A where ID in (select top 30 ID from A))
或
select top 10 * from A where ID not in (select top 30 ID from A)
2.
原表:
courseid coursename score
-------------------------------------
1 java 70
2 oracle 90
3 xml 40
4 jsp 30
5 servlet 80
-------------------------------------
为了便于阅读,查询此表后的结果显式如下(及格分数为60):
courseid coursename score mark
---------------------------------------------------
1 java 70 pass
2 oracle 90 pass
3 xml 40 fail
4 jsp 30 fail
5 servlet 80 pass
---------------------------------------------------
写出此查询语句
---------------------
select courseid, coursename ,score ,decode(sign(score-60),-1,'fail','pass') as mark from course
sql题练习链接:https://blog.csdn.net/qq_30946681/article/details/80233652