zoukankan      html  css  js  c++  java
  • 大数据面试题

    一点都没准备, what a shame!!!

    1. 给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
    
    方案1:可以估计每个文件安的大小为50G×64=320G,远远大于内存限制的4G。所以不可能将其完全加载到内存中处理。考虑采取分而治之的方法。
    
    s 遍历文件a,对每个url求取 hash(url)%1000,然后根据所取得的值将url分别存储到1000个小文件(记为a0...a999)中。这样每个小文件的大约为300M。
    
    s 遍历文件b,采取和a相同的方式将url分别存储到1000各小文件(记为hash(url)%1000)。这样处理后,所有可能相同的url都在对应的小文件(clip_image008)中,不对应的小文件不可能有相同的url。然后我们只要求出1000对小文件中相同的url即可。
    
    s 求每对小文件中相同的url时,可以把其中一个小文件的url存储到hash_set中。然后遍历另一个小文件的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。
    

    java 基础题, 太久没有做 java 需要看 api 才知道。。。就把集合框架的东西整理到一块儿吧

    ArrayList实现原理要点概括
    参考文献: 
    http://zhangshixi.iteye.com/blog/674856l 
    https://www.cnblogs.com/leesf456/p/5308358.html
    
    ArrayList是List接口的可变数组非同步实现,并允许包括null在内的所有元素。
    底层使用数组实现
    该集合是可变长度数组,数组扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量增长大约是其容量的1.5倍,这种操作的代价很高。
    采用了Fail-Fast机制,面对并发的修改时,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险
    remove方法会让下标到数组末尾的元素向前移动一个单位,并把最后一位的值置空,方便GC
    LinkedList实现原理要点概括
    参考文献: 
    1.http://www.cnblogs.com/ITtangtang/p/3948610.htmll 
    2.https://www.cnblogs.com/leesf456/p/5308843.html
    
    LinkedList是List接口的双向链表非同步实现,并允许包括null在内的所有元素。
    底层的数据结构是基于双向链表的,该数据结构我们称为节点
    双向链表节点对应的类Node的实例,Node中包含成员变量:prev,next,item。其中,prev是该节点的上一个节点,next是该节点的下一个节点,item是该节点所包含的值。
    它的查找是分两半查找,先判断index是在链表的哪一半,然后再去对应区域查找,这样最多只要遍历链表的一半节点即可找到
    HashMap实现原理要点概括
    参考文献:http://zhangshixi.iteye.com/blog/672697 
    参考文献:http://blog.csdn.net/lizhongkaide/article/details/50595719
    
    HashMap是基于哈希表的Map接口的非同步实现,允许使用null值和null键,但不保证映射的顺序。
    底层使用数组实现,数组中每一项是个单向链表,即数组和链表的结合体;当链表长度大于一定阈值时,链表转换为红黑树,这样减少链表查询时间。
    HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Node对象。HashMap底层采用一个Node[]数组来保存所有的key-value对,当需要存储一个Node对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Node时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Node。
    HashMap进行数组扩容需要重新计算扩容后每个元素在数组中的位置,很耗性能
    采用了Fail-Fast机制,通过一个modCount值记录修改次数,对HashMap内容的修改都将增加这个值。迭代器初始化过程中会将这个值赋给迭代器的expectedModCount,在迭代过程中,判断modCount跟expectedModCount是否相等,如果不相等就表示已经有其他线程修改了Map,马上抛出异常
    Hashtable实现原理要点概括
    参考文献:http://blog.csdn.net/zheng0518/article/details/42199477
    
    Hashtable是基于哈希表的Map接口的同步实现,不允许使用null值和null键
    底层使用数组实现,数组中每一项是个单链表,即数组和链表的结合体
    Hashtable在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。Hashtable底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
    synchronized是针对整张Hash表的,即每次锁住整张表让线程独占
    ConcurrentHashMap实现原理要点概括
    参考文献:http://blog.csdn.net/zheng0518/article/details/42199477
    
    ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。
    它使用了多个锁来控制对hash表的不同段进行的修改,每个段其实就是一个小的hashtable,它们有自己的锁。只要多个并发发生在不同的段上,它们就可以并发进行。
    ConcurrentHashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。Hashtable底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。
    与HashMap不同的是,ConcurrentHashMap使用多个子Hash表,也就是段(Segment)
    ConcurrentHashMap完全允许多个读操作并发进行,读操作并不需要加锁。如果使用传统的技术,如HashMap中的实现,如果允许可以在hash链的中间添加或删除元素,读操作不加锁将得到不一致的数据。ConcurrentHashMap实现技术是保证HashEntry几乎是不可变的。
    HashSet实现原理要点概括
    参考文献:http://zhangshixi.iteye.com/blog/673143l
    
    HashSet由哈希表(实际上是一个HashMap实例)支持,不保证set的迭代顺序,并允许使用null元素。
    基于HashMap实现,API也是对HashMap的行为进行了封装,可参考HashMap
    LinkedHashMap实现原理要点概括
    参考文献:http://zhangshixi.iteye.com/blog/673789l
    
    LinkedHashMap继承于HashMap,底层使用哈希表和双向链表来保存所有元素,并且它是非同步,允许使用null值和null键。
    基本操作与父类HashMap相似,通过重写HashMap相关方法,重新定义了数组中保存的元素Entry,来实现自己的链接列表特性。该Entry除了保存当前对象的引用外,还保存了其上一个元素before和下一个元素after的引用,从而构成了双向链接列表。
    LinkedHashSet实现原理要点概括
    参考文献:http://zhangshixi.iteye.com/blog/673319l
    
    对于LinkedHashSet而言,它继承与HashSet、又基于LinkedHashMap来实现的。LinkedHashSet底层使用LinkedHashMap来保存所有元素,它继承与HashSet,其所有的方法操作上又与HashSet相同。
    

    java 多线程中如何强行终止另一个线程? 这个 Future 确实不知道。。。谢谢面试官让我涨了知识

    原文地址

    说到多线程的future,百度 多线程 future,网上也有各式各样的例子,写的比我还要好,但是实在是这个模式或者说例子以及实用性太大了,我不得不拿出来讲,甚至在实际生产环境中也是可以用的.我呢,也是拿出网上的例子详细的讲一遍~~
    
    看下面的图↓↓↓↓↓
    
    传统下单流程.jpg
    如上图,传统的订单下单流程,首先减商品库存,然后生成订单,然后生成订单详情,再通知短信等等,全部逻辑程序都是串行执行的.假如我们的系统特别'困难',减商品库存要1秒,生成订单要1秒,生成详情也要1秒,发送短信有可能要5秒,这里还不算查询商品的库存够不够下单等等,那么一系列的操作就要花很多时间.
    
    那么引入多线程的future有什么好处呢?看下图↓↓↓↓↓↓↓
    
    多线程future下单流程.jpg
    看这图很简单,用户下单,future对象直接告诉你下单成功,返回给你一个假数据,同时自己偷偷的新建了一个或者几个线程处理其他业务逻辑,等逻辑处理完了,再返回一个正确的结果.
    
    然后是上代码~~
    
    public interface Data {
        String getRequest();
    }
    public class RealData implements Data {
        private String result;
    
        public RealData(String request) {
            System.out.println("根据" + request + "进行查询..,要花很久时间");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("操作完毕,获取结果");
            result = "查询结果";
        }
    
        public String getRequest() {
            return result;
        }
    }
    public class FutureData implements Data {
    
        private RealData realData;
    
        private boolean isReady = false;
    
        public synchronized String getRequest() {
    
            while (!isReady) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return this.realData.getRequest();
        }
    
        public synchronized void setRealData(RealData realData) {
            if (isReady) {
                return;
            }
            this.realData = realData;
            isReady = true;
            notify();
        }
    }
    
    public class FutureClient {
        public Data request(final String request) {
            final FutureData futureData = new FutureData();
    
            new Thread(new Runnable() {
    
                public void run() {
                    RealData realData = new RealData(request);
                    futureData.setRealData(realData);
                }
            }).start();
    
            return futureData;
        }
    }
    public class Main {
    
        public static void main(String[] args) {
            FutureClient fClient = new FutureClient();
            
            Data data = fClient.request("hello,world");
            
            System.out.println("请求发送成功...");
            System.out.println("干其他的事情...");
    
            String result = data.getRequest();
    
            System.out.println(result);
        }
    }
    一共5个类,刚开始看会有点懵逼,正常,我也是懵逼的,我到现在也还是懂了90%,为什么懂90%就敢讲,其实也差不多了~自己按照代码一个单词一个单词的教,自然就懂思想.就按照我贴的代码顺序我们一点一点看,这个模式很有意思的,真的能学到很多东西.
    
    首先看这个接口Data,只有一个方法getRequest(),返回String字符串.
    
    然后再看RealData这个类,实现了Data接口,首先他有构造函数,打印了两句话,然后中间sleep一下,做这个sleep我们可以想象成在处理业务逻辑.
    
    接着再看FutureData这个类,也实现了Data接口.先看FutureData的getRequest()方法,这个方法先死循环判断boolean,如果isReady是true,就阻塞着,不然就返回RealData真的getRequest()方法(真实的结果).然后再看setRealData(),判断isReady,如果是ture,直接return,如果不是就赋值RealData,并修改isReady,然后notify()..
    
    其实很好理解,不要看到synchronized,notify,wait就晕了,FutureData这个类干了啥,你想,wait什么?不就是等notify吗,如果没有notify,那我就得等着,等什么?还是等通知啊,只有通知了,那么我才能进行下去,进行下去什么?--->RealData.getRequset()啊,就是真实的数据,为什么要等?因为还在处理啊,只有真实的数据处理完了,然后通知,也就是说FutureData这个类的setRealData()只是起到通知的作用,再看setRealData()传入的是RealData对象,RealData干了啥事,不就是有个构造函数实现自己的业务吗,实现完了就可以通知!!还不懂,自己敲代码..结合我说的多读几遍,别被饶晕了~~~
    
    最后看FutureClient 这个类,最简单了,返回futureData,偷偷开了线程,看到RealData realData = new RealData(request)没有?就是开始执行业务了,然后当FutureData这个类的setRealData(RealData realData)时就通知了..我现在都100%懂了~~~~~~~
    
    最后Main方法就不说了~
    
    打印结果↓↓↓↓↓↓
    
    请求发送成功...
    干其他的事情...
    根据hello,world进行查询..,要花很久时间
    操作完毕,获取结果
    查询结果
    
    第四句话和第五话是2秒后才出来的~~~~
    
    上面的原理你可以不用懂,当然懂最好了,可以在面试官面前吹牛逼啊..future模式这么凶残,jdk也有实现的,在java.util.concurrent,又是concurrent,这个工具类真的是强大上代码,就不说了~
    
    import java.util.concurrent.Callable;
    
    public class RealData implements Callable<String> {
        private String Data;
    
        public RealData(String Data) {
            this.Data = Data;
        }
    
        public String call() throws Exception {
            //利用sleep来表示任务处理
            Thread.sleep(2000);
    
            return "这是处理"+Data+"结果";
        }
    }
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.FutureTask;
    
    public class Main {
    
        public static void main(String[] args) throws Exception {
            Long start = System.currentTimeMillis();
    
            FutureTask<String> futureTask = new FutureTask<>(new RealData("hello,world"));
            ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1);
            newFixedThreadPool.submit(futureTask);
    
            // 表示正在处理其他逻辑,或者业务
            Thread.sleep(1000);
    
            System.out.println("最后结果-->" + futureTask.get());
    
            Long end = System.currentTimeMillis();
    
            Long useTime = end - start;
    
            System.out.println("程序运行了-->" + useTime + "毫秒");
        }
    
    }
    最后奉上打印结果↓↓↓↓↓
    
    最后结果-->这是处理hello,world结果
    程序运行了-->2004毫秒
    
    看2秒就执行完了..最好自己敲一遍~~~~~
    
    

    乐观锁 与悲观锁脑袋一片空白,本可以答出来的。。。

    悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
    
    
    
    乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
    
    # 你眼中的 java 与 python 的区别在哪里
    我觉得呢 主要从 优缺点入手,虽然我说了一些看似有用的废话。。。
    还是参考下别人的吧
    
    
    1.难易度而言。python远远简单于java。
      2.开发速度。Python远优于java
      3.运行速度。java远优于标准python,pypy和cython可以追赶java,但是两者都没有成熟到可以做项目的程度。
      4.可用资源。java一抓一大把,python很少很少,尤其是中文资源。
      5.稳定程度。python3和2不兼容,造成了一定程度上的混乱以及大批类库失效。java由于有企业在背后支持所以稳定的多。
      6.是否开源。python从开始就是完全开源的。Java由sun开发,但现在有GUN的Openjdk可用,所以不用担心。
      7.编译还是解释。两者都是解释型。
      我理解,C好比手动挡车(编译型语言),java和python(解释型语言)好比自动档车。跑的最快的车都是手动档,但是对开不好的人来说,开自动档反而更快些。
      Kno有一篇文章谈到选择编程语言,“先确定你的需求”,不要由语言的简单还是复杂去觉定。只有能够编写你真正认为有用的程式,才能获得满足感,学习才能继续。
      那么java和python分别适用于什么样的环境呢。由sourceforge.net可以看出:
      最著名,久经考验的普通应用程序,基本都是c++写的。例如emule,7-zip,WinSCP,FileZilla等等等。
      一部分由java开发,例如最有名的OpenOffice。
      python写的很少,如Pidgin,FireBird。
      开发语言(有多少个程式由此语言开发)的排行如下:
      # Java46,202
      # C++36,895
      # PHP30,048
      # C28,075
      # C#13,476
      # Python13,379
      # JavaScript11,285
      # Perl9,216
      # Unix Shell3,869
      # Delphi/Kylix3,548
      # Visual Basic3,186
      # Visual Basic .NET
    
    
    作者:find goo
    链接:https://www.zhihu.com/question/20491745/answer/100741761
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    
    区别
    一、python虚拟机没有java强,java虚拟机是java的核心,python的核心是可以很方便地使用c语言函数或c++库。
    
    二、python是全动态性的,可以在运行时自己修改自己的代码,java只能通过变通方法实现。python的变量是动态的,而java的变量是静态的,需要事先声明,所以java ide的代码提示功能优于python ide。
    
    三,python的产生几十年了,几十年前面向过程是主流,所以用python有好多程序用的是面向过程设计方法,很多概念从c语言过来的,class在python中是后加入的,而java是为了实现没有指针的c++(当年com组件用的引用记数,java用的虚拟机),主要采用面向对象的设计方法,很多概念是oop的概念。面向过程,相对简洁直观,但容易设计出面条程序,面向对象,相对抽象优雅,但容易过度抽象。
    
    四,在实际使用的python入门简单,但要学会用python干活,需要再学习python各种库,pyhton的强大在于库,为什么python的库强大,原因是python的库可以用python,c语言,c++等设计,再提供给python使用,所以无论gpu运行,神经网络,智能算法,数据分析,图像处理,科学计算,各式各样的库在等着你用。而java没有python那么多的开源库,很多库是商业公司内部使用,或发布出来只是一个jar包,看不到原始代码。python虚拟机因为编译性没有java的支持的好(或者说故意这么设计的),一般直接使用源码(linux),或源码简单打个包(如pyexe)。
    
    五、python有很多虚拟机实现,如cython,Pyston,pypy,jython, IronPython等等,适合用于业务语言,或插件语言,或面向领域语言,而java因为虚拟机巨大,很少用于插件语言,发布也不方便。
    
    六、java主要用于商业逻辑强的领域,如商城系统,erp,oa,金融,保险等传统数据库事务领域,通过类似ssh框架事务代码,对商业数据库,如oralce,db2,sql server等支持较好,软件工程理念较强,适合软件工程式的多人开发模式。python主要用于web数据分析,科学计算,金融分析,信号分析,图像算法,数学计算,统计分析,算法建模,服务器运维,自动化操作,快速开发理念强,适合快速开发团队或个人敏捷模式。
    
    七、java的商业化公司支持多,如sap,oracle,ibm等,有商业化的容器,中间件,企业框架ejb。python的开源组织支持多,如qt,linux,google,很多开源程序都支持python, 如pyqt,redis,spark等。
    
    八、python用途最多的是脚本,java用途最多的是web,pyhotn是胶水,可以把各类不相关的东西粘在一起用,java是基佬,可以通过软件工程组成几百个人的团队和你pk,商业化气息重。不过我认为还是python强大,因为可以方便调用c或c++的库,但软件工程和商业化运作没有java好,适合快捷开发。
    
    九,关于钱。
    
    如果你想写程序卖软件用java,可用上ibm服务器,上oracle数据库,上EMC存储,价格高,商业采购公司喜欢这种高大上。如果你要直接用程序生成金钱用python,python可以实现宽客金融,数据回测,炒股,炒期权,炒黄金,炒比特币,对冲套利,统计套利,有很多开源库,数据分析库,机器学习库可以参考。
    
    十、java和python,都可以运行于linux操作系统,但很多linux可以原生支持python,java需要自行安装。java和python强于c#的原因大于支持linux,支持osx,支持unix,支持arm。java和python比c++受欢迎的原因在于不需要指针。
    
    十一、对于移动互联网,python只能通过运行库运行于安卓或ios,java原生支持安卓开发,但不能用ios中。
    
    十二、对于大数据,hadoop用java开的, spark用Scala开发,用python调用spark再分析更方便
    
    
    大神不会告诉你的Java与Python的区别
    http://www.codesec.net/view/517408.html
    
    
    对比java和python对比
    http://www.cnblogs.com/kungfupanda/p/4601947.html
    
    
    Java 和 Python 有哪些区别?
    https://www.zhihu.com/question/20491745
    到底什么是Python?你可以在回答中与其他技术进行对比(也鼓励这样做)。
    
    答案
    
    下面是一些关键点:
    
    Python是一种解释型语言。这就是说,与C语言和C的衍生语言不同,Python代码在运行之前不需要编译。其他解释型语言还包括PHP和Ruby。
    Python是动态类型语言,指的是你在声明变量时,不需要说明变量的类型。你可以直接编写类似x=111和x="I'm a string"这样的代码,程序不会报错。
    Python非常适合面向对象的编程(OOP),因为它支持通过组合(composition)与继承(inheritance)的方式定义类(class)。Python中没有访问说明符(access specifier,类似C++中的public和private),这么设计的依据是“大家都是成年人了”。
    在Python语言中,函数是第一类对象(first-class objects)。这指的是它们可以被指定给变量,函数既能返回函数类型,也可以接受函数作为输入。类(class)也是第一类对象。
    Python代码编写快,但是运行速度比编译语言通常要慢。好在Python允许加入基于C语言编写的扩展,因此我们能够优化代码,消除瓶颈,这点通常是可以实现的。numpy就是一个很好地例子,它的运行速度真的非常快,因为很多算术运算其实并不是通过Python实现的。
    Python用途非常广泛——网络应用,自动化,科学建模,大数据应用,等等。它也常被用作“胶水语言”,帮助其他语言和组件改善运行状况。
    Python让困难的事情变得容易,因此程序员可以专注于算法和数据结构的设计,而不用处理底层的细节。
    为什么提这个问题:
    
    如果你应聘的是一个Python开发岗位,你就应该知道这是门什么样的语言,以及它为什么这么酷。以及它哪里不好。
    
    

    SQL 部分知识, 这部分还好没有出什么大丑!其实这个面试题是比较简单的,而且我自认为还没有我写不出来的SQL 毕竟写了好多年ETL,感觉什么奇怪SQL都写过了

    题目: 找出公司 网站首次被访问url的次数

    这一题要分两步来走,一 先取到 首次被访问的 url 集合,二 关联 总数据集与 第一步筛选出的 url,然后做分组 count
    
    第一步:  根据session id 分组,按照 访问时间升序 编号,取第 rownumber = 1 的 那条
    具体大概如下: 
    with cte as 
    (select  (row_number()over(partition by sessionId order by visit_datetime ASC) as rn 
    ... 其他列
    from table
    )
    第二步:
    关联  第一步 结果集中 filter 出 rn = 1  的,再按照 url 分组 聚合 count
    
    select t.url
                ,count(*) as cnt 
                                  from table  t 
                                                    inner join cte on  t.url = cte.url  
                                  where cte.rn = 1 group by t.url(其实这里应该是 url 对应的 id 。。。讲道理 int 比 varchar 做关联查询会高效很多)
    
    ---- Oracle, SQL Server 都有 ROW_NUMBER 函数可以用来编号,但是像mysql这种数据库就要找 min(id) 这类方法来替代了。。。
    
    最后2、:补充一个最最重要,最最坑爹,最最有难度的一个题目:一个每秒百万级访问量的互联网服务器,每个访问都有数据计算和I/O操作,如果让你设计,你怎么设计?
    异步 IO  + 多进程   类似于 爬虫 设计
    

    最后总结一波吧:
    暂时目前脑袋里的记忆大概只有这些吧,还是要端正态度去迎接每一次面试,主要是最近一直忙于 python 项目,对 java 很多东西都感觉生疏了,其实我比较纳闷 AOP 这些特性怎么不问,哈哈,其实我对这些玩意儿研究的多。。。

    如果有来生,一个人去远行,看不同的风景,感受生命的活力。。。
  • 相关阅读:
    PHP保留小数的相关方法
    ASP.NET Core MVC 之过滤器(Filter)
    ASP.NET Core MVC 之控制器(Controller)
    ASP.NET Core MVC 之视图组件(View Component)
    ASP.NET Core MVC 之局部视图(Partial Views)
    标签助手(TagHelper)
    ASP.NET Core MVC 之布局(Layout)
    ASP.NET Core MVC 之视图(Views)
    ASP.NET Core MVC 之模型(Model)
    九卷读书:淘宝从小到大的发展 -重读《淘宝技术这十年》
  • 原文地址:https://www.cnblogs.com/Frank99/p/9324311.html
Copyright © 2011-2022 走看看