• 生成类似于MongoDB产生的ObjectId


      1 package com.jt.boot.utils;
      2 
      3 import com.google.common.base.Objects;
      4 
      5 import java.net.NetworkInterface;
      6 import java.nio.ByteBuffer;
      7 import java.util.Date;
      8 import java.util.Enumeration;
      9 import java.util.Random;
     10 import java.util.concurrent.atomic.AtomicInteger;
     11 import java.util.logging.Level;
     12 import java.util.logging.Logger;
     13 
     14 /**
     15  * <p>A globally unique identifier for objects.</p>
     16  * <p/>
     17  * <p>Consists of 12 bytes, divided as follows:</p>
     18  * <table border="1">
     19  * <caption>ObjectID layout</caption>
     20  * <tr>
     21  * <td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td><td>11</td>
     22  * </tr>
     23  * <tr>
     24  * <td colspan="4">time</td><td colspan="3">machine</td> <td colspan="2">pid</td><td colspan="3">inc</td>
     25  * </tr>
     26  * </table>
     27  * <p/>
     28  * <p>Instances of this class are immutable.</p>
     29  */
     30 public class ObjectId implements Comparable<ObjectId>, java.io.Serializable {
     31 
     32     private final int _time;
     33     private final int _machine;
     34     private final int _inc;
     35     private boolean _new;
     36     private static final int _genmachine;
     37 
     38     private static AtomicInteger _nextInc = new AtomicInteger((new Random()).nextInt());
     39 
     40     private static final long serialVersionUID = -4415279469780082174L;
     41 
     42     private static final Logger LOGGER = Logger.getLogger("org.bson.ObjectId");
     43 
     44     /**
     45      * Create a new object id.
     46      */
     47     public ObjectId() {
     48         _time = (int) (System.currentTimeMillis() / 1000);
     49         _machine = _genmachine;
     50         _inc = _nextInc.getAndIncrement();
     51         _new = true;
     52     }
     53     
     54     public static String id() {
     55         return get().toHexString();
     56     }
     57 
     58     /**
     59      * Gets a new object id.
     60      *
     61      * @return the new id
     62      */
     63     public static ObjectId get() {
     64         return new ObjectId();
     65     }
     66 
     67     /**
     68      * Checks if a string could be an {@code ObjectId}.
     69      *
     70      * @param s a potential ObjectId as a String.
     71      * @return whether the string could be an object id
     72      * @throws IllegalArgumentException if hexString is null
     73      */
     74     public static boolean isValid(String s) {
     75         if (s == null)
     76             return false;
     77 
     78         final int len = s.length();
     79         if (len != 24)
     80             return false;
     81 
     82         for (int i = 0; i < len; i++) {
     83             char c = s.charAt(i);
     84             if (c >= '0' && c <= '9')
     85                 continue;
     86             if (c >= 'a' && c <= 'f')
     87                 continue;
     88             if (c >= 'A' && c <= 'F')
     89                 continue;
     90 
     91             return false;
     92         }
     93 
     94         return true;
     95     }
     96 
     97 
     98     /**
     99      * Converts this instance into a 24-byte hexadecimal string representation.
    100      *
    101      * @return a string representation of the ObjectId in hexadecimal format
    102      */
    103     public String toHexString() {
    104         final StringBuilder buf = new StringBuilder(24);
    105         for (final byte b : toByteArray()) {
    106             buf.append(String.format("%02x", b & 0xff));
    107         }
    108         return buf.toString();
    109     }
    110 
    111     /**
    112      * Convert to a byte array.  Note that the numbers are stored in big-endian order.
    113      *
    114      * @return the byte array
    115      */
    116     public byte[] toByteArray() {
    117         byte b[] = new byte[12];
    118         ByteBuffer bb = ByteBuffer.wrap(b);
    119         // by default BB is big endian like we need
    120         bb.putInt(_time);
    121         bb.putInt(_machine);
    122         bb.putInt(_inc);
    123         return b;
    124     }
    125 
    126     private int _compareUnsigned(int i, int j) {
    127         long li = 0xFFFFFFFFL;
    128         li = i & li;
    129         long lj = 0xFFFFFFFFL;
    130         lj = j & lj;
    131         long diff = li - lj;
    132         if (diff < Integer.MIN_VALUE)
    133             return Integer.MIN_VALUE;
    134         if (diff > Integer.MAX_VALUE)
    135             return Integer.MAX_VALUE;
    136         return (int) diff;
    137     }
    138 
    139     public int compareTo(ObjectId id) {
    140         if (id == null)
    141             return -1;
    142 
    143         int x = _compareUnsigned(_time, id._time);
    144         if (x != 0)
    145             return x;
    146 
    147         x = _compareUnsigned(_machine, id._machine);
    148         if (x != 0)
    149             return x;
    150 
    151         return _compareUnsigned(_inc, id._inc);
    152     }
    153 
    154     /**
    155      * Gets the timestamp (number of seconds since the Unix epoch).
    156      *
    157      * @return the timestamp
    158      */
    159     public int getTimestamp() {
    160         return _time;
    161     }
    162 
    163     /**
    164      * Gets the timestamp as a {@code Date} instance.
    165      *
    166      * @return the Date
    167      */
    168     public Date getDate() {
    169         return new Date(_time * 1000L);
    170     }
    171 
    172 
    173     /**
    174      * Gets the current value of the auto-incrementing counter.
    175      *
    176      * @return the current counter value.
    177      */
    178     public static int getCurrentCounter() {
    179         return _nextInc.get();
    180     }
    181 
    182 
    183     static {
    184 
    185         try {
    186             // build a 2-byte machine piece based on NICs info
    187             int machinePiece;
    188             {
    189                 try {
    190                     StringBuilder sb = new StringBuilder();
    191                     Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
    192                     while (e.hasMoreElements()) {
    193                         NetworkInterface ni = e.nextElement();
    194                         sb.append(ni.toString());
    195                     }
    196                     machinePiece = sb.toString().hashCode() << 16;
    197                 } catch (Throwable e) {
    198                     // exception sometimes happens with IBM JVM, use random
    199                     LOGGER.log(Level.WARNING, e.getMessage(), e);
    200                     machinePiece = (new Random().nextInt()) << 16;
    201                 }
    202                 LOGGER.fine("machine piece post: " + Integer.toHexString(machinePiece));
    203             }
    204 
    205             // add a 2 byte process piece. It must represent not only the JVM but the class loader.
    206             // Since static var belong to class loader there could be collisions otherwise
    207             final int processPiece;
    208             {
    209                 int processId = new Random().nextInt();
    210                 try {
    211                     processId = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();
    212                 } catch (Throwable t) {
    213                 }
    214 
    215                 ClassLoader loader = ObjectId.class.getClassLoader();
    216                 int loaderId = loader != null ? System.identityHashCode(loader) : 0;
    217 
    218                 StringBuilder sb = new StringBuilder();
    219                 sb.append(Integer.toHexString(processId));
    220                 sb.append(Integer.toHexString(loaderId));
    221                 processPiece = sb.toString().hashCode() & 0xFFFF;
    222                 LOGGER.fine("process piece: " + Integer.toHexString(processPiece));
    223             }
    224 
    225             _genmachine = machinePiece | processPiece;
    226             LOGGER.fine("machine : " + Integer.toHexString(_genmachine));
    227         } catch (Exception e) {
    228             throw new RuntimeException(e);
    229         }
    230 
    231     }
    232 
    233     @Override
    234     public boolean equals(Object o) {
    235         if (this == o) return true;
    236         if (o == null || getClass() != o.getClass()) return false;
    237 
    238         ObjectId that = (ObjectId) o;
    239 
    240         return Objects.equal(this.serialVersionUID, that.serialVersionUID) &&
    241                 Objects.equal(this.LOGGER, that.LOGGER) &&
    242                 Objects.equal(this._time, that._time) &&
    243                 Objects.equal(this._machine, that._machine) &&
    244                 Objects.equal(this._inc, that._inc) &&
    245                 Objects.equal(this._new, that._new) &&
    246                 Objects.equal(this._nextInc, that._nextInc) &&
    247                 Objects.equal(this._genmachine, that._genmachine);
    248     }
    249 
    250     @Override
    251     public int hashCode() {
    252         return Objects.hashCode(serialVersionUID, LOGGER, _time, _machine, _inc, _new,
    253                 _nextInc, _genmachine);
    254     }
    255 
    256     public static void main(String[] args) {
    257         System.out.println(new ObjectId().toHexString());
    258         System.out.println(new ObjectId().toHexString());
    259         System.out.println(new ObjectId().toHexString());
    260     }
    261 }
  • 相关阅读:
    NOIP2009 靶形数独
    NOIP2014 寻找道路
    NOIP2005 篝火晚会
    NOIP2014 联合权值
    NOIP2011 选择客栈
    luogu2659 美丽的序列
    NOIP2008 传纸条
    vijos1642 班长的任务
    codevs1427 RQNOJ204 特种部队
    AC自动机
  • 原文地址:https://www.cnblogs.com/wihainan/p/6237005.html
Copyright © 2020-2023  润新知