什么是大公司?50行Java就知道了

234 阅读8分钟

最近是金三银四跳槽季,网上天天看到别人说:

  • 江某某进了大公司
  • 克某某进入了中公司
  • 郎某某进入了小公司

那么什么是大公司,什么是小公司,到底是以什么作为依据来判断的,有没有什么标准呢?

有的, 国家统计局.

公司大小怎么判断?

要判断公司大小,首先要划分行业, 公司大小判断随着行业不同而变化, 每个行业都不同.

行业的划分, 是按照《国民经济行业分类》(GB/T 4754—2017)进行的.国标最近一次修订是2017年,因此统计局随之给出了相应统计标准的修改:《统计上大中小微型企业划分办法(2017)》 .

大型、中型和小型企业须同时满足所列指标的下限,否则下划一档;微型企业只须满足所列指标中的一项即可。

规则分析

这个表格, 按我粗浅的理解是这样的.

  • 每个行业都有对应的指标
  • 指标是根据3个数轴上的点划分的4个区间
  • 附录里的注释1说明, 所有指标中评分最低的那个为准

举例说明,以餐饮业为例,分别考核从业人员营业收入两个指标.

  • 从业人员划分界限分别为: 10,100,2000,这里把数轴划为 -∞,10),[10,100),[100,2000),[2000,+∞).

  • 营业收入, 划分界限分别为: 100,2000,10000

  • 若一公司员工1人, 收入10001, 很明显,应该按照最低的人员这项定为微型

(注, 这里可能理解的规则不对, 下划一档这词没搞明白,按照else if理解的而不是else)

数据整理

很明显, 我们这里需要的是把表格中的相关信息都整理出来,才能写代码.

这是个体力活,我已经整理过了.输出格式是以行业为key,规则列表为value的一个map结构,输出为JSON是这样的.

规则JSON

{"农、林、牧、渔业":[{"key":"Y","value":[50,500,20000]}],"工业":[{"key":"X","value":[20,300,1000]},{"key":"Y","value":[300,2000,40000]}],"建筑业":[{"key":"Y","value":[300,6000,80000]},{"key":"Z","value":[300,5000,80000]}],"批发业":[{"key":"X","value":[5,20,200]},{"key":"Y","value":[1000,5000,40000]}],"零售业":[{"key":"X","value":[10,50,300]},{"key":"Y","value":[100,500,20000]}],"交通运输业":[{"key":"X","value":[20,300,1000]},{"key":"Y","value":[200,3000,30000]}],"仓储业":[{"key":"X","value":[20,100,200]},{"key":"Y","value":[100,1000,30000]}],"邮政业":[{"key":"X","value":[20,300,1000]},{"key":"Y","value":[100,2000,30000]}],"住宿业":[{"key":"X","value":[10,100,300]},{"key":"Y","value":[100,2000,10000]}],"餐饮业":[{"key":"X","value":[10,100,300]},{"key":"Y","value":[100,2000,10000]}],"信息传输业":[{"key":"X","value":[10,100,2000]},{"key":"Y","value":[100,1000,100000]}],"软件和信息技术服务业":[{"key":"X","value":[10,100,300]},{"key":"Y","value":[50,1000,10000]}],"房地产开发经营":[{"key":"Y","value":[100,1000,200000]},{"key":"Z","value":[2000,5000,10000]}],"物业管理":[{"key":"X","value":[100,300,1000]},{"key":"Y","value":[500,1000,5000]}],"租赁和商务服务业":[{"key":"X","value":[10,100,300]},{"key":"Z","value":[100,8000,120000]}],"其他未列明行业":[{"key":"X","value":[10,100,300]}]}

附整理代码


static final String s = "农、林、牧、渔业	营业收入(Y)	万元	Y≥20000	 500≤Y<20000	 50≤Y<500	Y<50\n工业 *	从业人员(X)	人	X≥1000	300≤X<1000	 20≤X<300	X<20\n	营业收入(Y)	万元	Y≥40000	2000≤Y<40000	 300≤Y<2000	Y<300\n建筑业	营业收入(Y)	万元	Y≥80000	6000≤Y<80000	 300≤Y<6000	Y<300\n	资产总额(Z)	万元	Z≥80000	5000≤Z<80000	 300≤Z<5000	Z<300\n批发业	从业人员(X)	人	X≥200	20≤X<200	 5≤X<20	X<5\n	营业收入(Y)	万元	Y≥40000	5000≤Y<40000	1000≤Y<5000	Y<1000\n零售业	从业人员(X)	人	X≥300	50≤X<300	10≤X<50	X<10\n	营业收入(Y)	万元	Y≥20000	 500≤Y<20000	100≤Y<500	Y<100\n交通运输业 *	从业人员(X)	人	X≥1000	300≤X<1000	 20≤X<300	X<20\n	营业收入(Y)	万元	Y≥30000	3000≤Y<30000	 200≤Y<3000	Y<200\n仓储业	从业人员(X)	人	X≥200	100≤X<200	 20≤X<100	X<20\n	营业收入(Y)	万元	Y≥30000	1000≤Y<30000	 100≤Y<1000	Y<100\n邮政业	从业人员(X)	人	X≥1000	300≤X<1000	 20≤X<300	X<20\n	营业收入(Y)	万元	Y≥30000	2000≤Y<30000	 100≤Y<2000	Y<100\n住宿业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥10000	2000≤Y<10000	 100≤Y<2000	Y<100\n餐饮业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥10000	2000≤Y<10000	 100≤Y<2000	Y<100\n信息传输业 *	从业人员(X)	人	X≥2000	100≤X<2000	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥100000	 1000≤Y<100000	 100≤Y<1000	Y<100\n软件和信息技术服务业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥10000	1000≤Y<10000	  50≤Y<1000	Y<50\n房地产开发经营	营业收入(Y)	万元	Y≥200000	 1000≤Y<200000	 100≤Y<1000	Y<100\n	资产总额(Z)	万元	Z≥10000	5000≤Z<10000	2000≤Z<5000   	Z<2000\n物业管理	从业人员(X)	人	X≥1000	300≤X<1000	100≤X<300	X<100\n	营业收入(Y)	万元	Y≥5000	1000≤Y<5000	 500≤Y<1000	Y<500\n租赁和商务服务业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	资产总额(Z)	万元	Z≥120000	 8000≤Z<120000	 100≤Z<8000	Z<100\n其他未列明行业 *	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10";

final static LinkedMultiValueMap<String, Pair<String, List<Integer>>> map = new LinkedMultiValueMap<>();

String[] code = new String[1];
Arrays.stream(s.split("\\n")).forEach(line -> { if (!line.matches("^\\s+.*$")) { code[0] = line.split("\\s")[0]; line = line.substring(line.split("\\t")[0].length()); } map.add(code[0], Pair.of(line.substring(line.indexOf("(") + 1, line.indexOf("(") + 2), Arrays.stream(line.trim().split("\\t")).skip(3).map(x -> Integer.decode(x.substring(x.lastIndexOf("<") + 1).trim())).sorted().collect(Collectors.toList()))); });
System.out.println(JSON.toJSONString(map,true));

规则运算

有了规则当然是要用的, 这个表格里一共规定了3个指标:

  1. 从业人员(X)
  2. 营业收入(Y)
  3. 资产总额(Z)

因此可以设计如下方法:

String calc(String industry, Integer X, Integer Y, Integer Z);

3个指标都不是一定有值的, 所以这里可null,用包装类即可.

实现代码

这里做了个小逻辑

  • 微型企业可以缺必须指标,其他的不可以会报错.

  • industry名称假定和表格里的一模一样,这个需要调用方自己保证或处理.


static final String[] type=new String[]{"微","小","中","大"};

public static String calc(String industry, Integer X, Integer Y, Integer Z) {
        var rules = map.getOrDefault(industry,map.get("其他未列明行业"));
        List<Integer> scores = new ArrayList<>(rules.size());
        for (Pair<String, List<Integer>> rule : rules) {
            Integer value=null;
            String key = rule.getKey();
            switch (key) {
                case "X": value = X; break;
                case "Y": value = Y; break;
                case "Z": value = Z; break;
            }
            int level = value == null ? Integer.MAX_VALUE : locate(rule.getValue(), value);
            scores.add(level);
        }
        Integer min = Collections.min(scores);
        if(min!=0 && scores.contains(Integer.MAX_VALUE))throw new IllegalArgumentException();
        return type[min];
}

区间判断代码

数字落在哪个区间, 这个逻辑写了一会比较, 后来发现是我想多了,没那么复杂.

这里只需要计算一个数字从左到右,超过了几个指标即可.比如使用餐饮业的[10,100,2000],从左到右逐个比较,

  • 一个坎儿都过不去的是0,对应<10
  • 过去1个坎过不了第二个的是1,对应[10,100)
  • .....以此类推

理顺这个以后写成代码就简单了,就是一个简单的for循环


    static int locate(List<Integer> pivotal, Integer x) {
        int i = 0;
        for (; i < pivotal.size(); i++) {
            if (x < pivotal.get(i)) {
                return i;
            }
        }
        return i;
    }

测试


public static void main(String[] args) {
        Assert.assertEquals( "微",calc("工业", 19, 40000, null));
        Assert.assertEquals( "小",(calc("工业", 20, 40000, null)));
        Assert.assertEquals( "中",(calc("工业", 300, 40000, null)));
        Assert.assertEquals( "大",(calc("工业", 1000, 40000, null)));

        Assert.assertEquals( "微",calc("工业", 19, 2000, null));
        Assert.assertEquals( "小",(calc("工业", 20, 2000, null)));
        Assert.assertEquals( "中",(calc("工业", 300, 2000, null)));
        Assert.assertEquals( "中",(calc("工业", 1000, 2000, null)));

        Assert.assertEquals( "微",calc("工业", 19, 300, null));
        Assert.assertEquals( "小",(calc("工业", 20, 300, null)));
        Assert.assertEquals( "小",(calc("工业", 300, 300, null)));
        Assert.assertEquals( "小",(calc("工业", 1000, 300, null)));

        Assert.assertEquals( "微",calc("工业", 19, 200, null));
        Assert.assertEquals( "微",(calc("工业", 20, 200, null)));
        Assert.assertEquals( "微",(calc("工业", 300, 200, null)));
        Assert.assertEquals( "微",(calc("工业", 1000, 200, null)));
}

简单用了工业试了下, 理论上没问题了. 没有进行详测

后话

好了. 今天的水文时间到此结束.

这主要是个洗数据的脏活儿, json洗出来以后就算结束了.后面我的实现只是一孔之见.

对于下调一档那块, 还没理解明白, 按照理解的方式,找最低级实现的.如果下调一档指的是, 一个指标是,另一个指标是,最高的那个往下调一档变成的话, 代码可能需要写成这样,不太确定.

 
Integer max = Collections.max(scores);
if(scores.stream().anyMatch(x->!x.equals(max))){
  return type[max-1];
}

暂时我还是按照取最小来处理.

附全代码

import org.apache.commons.lang3.tuple.Pair;
import org.springframework.util.LinkedMultiValueMap;
import java.util.*;
import java.util.stream.Collectors;

public class CorpSize {
    private static final String s = "农、林、牧、渔业	营业收入(Y)	万元	Y≥20000	 500≤Y<20000	 50≤Y<500	Y<50\n工业 *	从业人员(X)	人	X≥1000	300≤X<1000	 20≤X<300	X<20\n	营业收入(Y)	万元	Y≥40000	2000≤Y<40000	 300≤Y<2000	Y<300\n建筑业	营业收入(Y)	万元	Y≥80000	6000≤Y<80000	 300≤Y<6000	Y<300\n	资产总额(Z)	万元	Z≥80000	5000≤Z<80000	 300≤Z<5000	Z<300\n批发业	从业人员(X)	人	X≥200	20≤X<200	 5≤X<20	X<5\n	营业收入(Y)	万元	Y≥40000	5000≤Y<40000	1000≤Y<5000	Y<1000\n零售业	从业人员(X)	人	X≥300	50≤X<300	10≤X<50	X<10\n	营业收入(Y)	万元	Y≥20000	 500≤Y<20000	100≤Y<500	Y<100\n交通运输业 *	从业人员(X)	人	X≥1000	300≤X<1000	 20≤X<300	X<20\n	营业收入(Y)	万元	Y≥30000	3000≤Y<30000	 200≤Y<3000	Y<200\n仓储业	从业人员(X)	人	X≥200	100≤X<200	 20≤X<100	X<20\n	营业收入(Y)	万元	Y≥30000	1000≤Y<30000	 100≤Y<1000	Y<100\n邮政业	从业人员(X)	人	X≥1000	300≤X<1000	 20≤X<300	X<20\n	营业收入(Y)	万元	Y≥30000	2000≤Y<30000	 100≤Y<2000	Y<100\n住宿业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥10000	2000≤Y<10000	 100≤Y<2000	Y<100\n餐饮业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥10000	2000≤Y<10000	 100≤Y<2000	Y<100\n信息传输业 *	从业人员(X)	人	X≥2000	100≤X<2000	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥100000	 1000≤Y<100000	 100≤Y<1000	Y<100\n软件和信息技术服务业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	营业收入(Y)	万元	Y≥10000	1000≤Y<10000	  50≤Y<1000	Y<50\n房地产开发经营	营业收入(Y)	万元	Y≥200000	 1000≤Y<200000	 100≤Y<1000	Y<100\n	资产总额(Z)	万元	Z≥10000	5000≤Z<10000	2000≤Z<5000   	Z<2000\n物业管理	从业人员(X)	人	X≥1000	300≤X<1000	100≤X<300	X<100\n	营业收入(Y)	万元	Y≥5000	1000≤Y<5000	 500≤Y<1000	Y<500\n租赁和商务服务业	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10\n	资产总额(Z)	万元	Z≥120000	 8000≤Z<120000	 100≤Z<8000	Z<100\n其他未列明行业 *	从业人员(X)	人	X≥300	100≤X<300	 10≤X<100	X<10";
    private static final String[] type=new String[]{"微","小","中","大"};
    private final static LinkedMultiValueMap<String, Pair<String, List<Integer>>> map = new LinkedMultiValueMap<>();
    static {
        String[] code = new String[1];
        Arrays.stream(s.split("\\n")).forEach(line -> { if (!line.matches("^\\s+.*$")) { code[0] = line.split("\\s")[0]; line = line.substring(line.split("\\t")[0].length()); } map.add(code[0], Pair.of(line.substring(line.indexOf("(") + 1, line.indexOf("(") + 2), Arrays.stream(line.trim().split("\\t")).skip(3).map(x -> Integer.decode(x.substring(x.lastIndexOf("<") + 1).trim())).sorted().collect(Collectors.toList()))); });
    }

    public static String calc(String industry, Integer X, Integer Y, Integer Z) {
        var rules = map.getOrDefault(industry,map.get("其他未列明行业"));
        List<Integer> scores = new ArrayList<>(rules.size());
        for (Pair<String, List<Integer>> rule : rules) {
            Integer value=null;
            String key = rule.getKey();
            switch (key) {
                case "X": value = X; break;
                case "Y": value = Y; break;
                case "Z": value = Z; break;
            }
            int level = value == null ? Integer.MAX_VALUE : locate(rule.getValue(), value);
            scores.add(level);
        }
        Integer min = Collections.min(scores);
        if(min!=0 && scores.contains(Integer.MAX_VALUE))throw new IllegalArgumentException();
        return type[min];
    }

    static int locate(List<Integer> pivotal, Integer x) {
        int i = 0;
        for (; i < pivotal.size(); i++) {
            if (x < pivotal.get(i)) {
                return i;
            }
        }
        return i;
    }
}

这里还有很多遗留问题.

  • 为了微信排版篇幅问题,故意用了很多1行风格的代码.
  • 农、林、牧、渔业暂时是合并的key, 可以考虑拆开.
  • 行业名称精确匹配,容易导致匹配不到行业进入默认规则,这块可以自行处理.

有好事的朋友愿意接着改Java的话,可以接着拿去改,也可以直接拿整理好的json去用.授权协议和以前, 留言即可获得任意权.

640watermark.gif