• 大数据面试题


    一点都没准备, 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 这些特性怎么不问,哈哈,其实我对这些玩意儿研究的多。。。

    如果有来生,一个人去远行,看不同的风景,感受生命的活力。。。
  • 相关阅读:
    市面上的系统.
    linux /dev 常见特殊设备介绍与应用[loop,null,zero,full,random]
    Linux command 系统快捷键
    Qtcreator中常用快捷键总结
    开始新的博客征途
    css选择器顺序的小技巧
    推荐20个很有帮助的web前端开发教程
    炙手可热的前端资源大集合
    一款纯css实现的垂直时间线效果
    15款极具创造性的艺术创意
  • 原文地址:https://www.cnblogs.com/Frank99/p/9324311.html
Copyright © 2020-2023  润新知