竞争无处不在,青春永不言败!专业撸代码,副业修bug

Talk is cheap , show me the code!



大数据面试题

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

posted @ 2018-07-17 16:57  云雾散人  阅读(274)  评论(0编辑  收藏  举报

Your attitude not your aptitude will determine your altitude!

如果有来生,一个人去远行,看不同的风景,感受生命的活力!