com.doctor.other.concurrent_hash_map_based_table.ConcurrentHashMapBasedTable.java Source code

Java tutorial

Introduction

Here is the source code for com.doctor.other.concurrent_hash_map_based_table.ConcurrentHashMapBasedTable.java

Source

/*
 * Copyright (C) 2014-present  The  openSourcLibrary-2015  Authors
 *
 * https://github.com/sdcuike
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.doctor.other.concurrent_hash_map_based_table;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;

/**
 * ConcurrentHashMapBasedTable (?HBase??
 * 
 * 
 * @author doctor
 *
 * @time 2015727 ?2:18:27
 */
public final class ConcurrentHashMapBasedTable<T> {
    private static final Logger log = LoggerFactory.getLogger(ConcurrentHashMapBasedTable.class);

    private int ttl = 3;

    private ConcurrentHashMap<String, ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>>> table = new ConcurrentHashMap<>();
    private ScheduledExecutorService executorService = Executors
            .newScheduledThreadPool(Runtime.getRuntime().availableProcessors() + 1);

    public ConcurrentHashMapBasedTable() {

    }

    public ConcurrentHashMapBasedTable(int ttl) {
        this.ttl = ttl;
    }

    /**
     * 
     * @param rowKey
     * @param columnKey
     * @param timesplice
     *            ?:201572701
     * @param value
     * @return
     */
    public boolean put(final String rowKey, final String columnKey, final String timesplice, final T value) {
        Preconditions.checkState(StringUtils.isNotBlank(rowKey), "rowKey is blank");
        Preconditions.checkState(StringUtils.isNotBlank(columnKey), "columnKey is blank");
        Preconditions.checkState(StringUtils.isNotBlank(timesplice), "timesplice is blank");
        Preconditions.checkNotNull(value, "value is null");

        ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>> row = table.get(rowKey);
        if (row == null) {
            table.putIfAbsent(rowKey,
                    new ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>>());
        }

        row = table.get(rowKey);

        ConcurrentSkipListMap<String, ConcurrentSet<T>> column = row.get(columnKey);
        if (column == null) {
            row.putIfAbsent(columnKey, new ConcurrentSkipListMap<String, ConcurrentSet<T>>());
        }

        column = row.get(columnKey);

        ConcurrentSet<T> values = column.get(timesplice);
        if (values == null) {
            column.putIfAbsent(timesplice, new ConcurrentSet<>());
        }

        values = column.get(timesplice);
        return values.add(value);
    }

    public boolean put(final String rowKey, final String columnKey, final LocalDateTime time, final T value) {
        return this.put(rowKey, columnKey, time.format(Util.timeFormatter), value);
    }

    public List<T> get(final String rowKey, final String columnKey, final String timesplice) {
        Preconditions.checkState(StringUtils.isNotBlank(rowKey), "rowKey is blank");
        Preconditions.checkState(StringUtils.isNotBlank(columnKey), "columnKey is blank");
        Preconditions.checkState(StringUtils.isNotBlank(timesplice), "timesplice is blank");

        ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>> row = table.get(rowKey);
        if (row == null) {
            return Arrays.asList();
        }

        ConcurrentSkipListMap<String, ConcurrentSet<T>> column = row.get(columnKey);
        if (column == null) {
            return Arrays.asList();
        }

        ConcurrentSet<T> values = column.get(timesplice);

        if (values == null) {
            return Arrays.asList();
        }

        return values.stream().collect(Collectors.toList());
    }

    public List<T> get(final String rowKey, final String columnKey) {
        Preconditions.checkState(StringUtils.isNotBlank(rowKey), "rowKey is blank");
        Preconditions.checkState(StringUtils.isNotBlank(columnKey), "columnKey is blank");

        ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>> row = table.get(rowKey);
        if (row == null) {
            return Arrays.asList();
        }

        ConcurrentSkipListMap<String, ConcurrentSet<T>> column = row.get(columnKey);
        if (column == null) {
            return Arrays.asList();
        }

        return column.values().parallelStream().flatMap(v -> v.parallelStream()).collect(Collectors.toList());
    }

    public Long getSumForRowKey(final String rowKey) {
        if (StringUtils.isBlank(rowKey)) {
            return Long.valueOf(0L);
        }

        ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>> map = table.get(rowKey);
        if (map == null) {
            return Long.valueOf(0L);
        }

        return map.values().parallelStream().flatMap(k -> k.values().parallelStream()).mapToLong(k2 -> k2.size())
                .sum();
    }

    public Long getSumForRowColumnKey(final String rowKey, final String columnKey) {
        if (StringUtils.isBlank(rowKey) || StringUtils.isBlank(columnKey)) {
            return Long.valueOf(0L);
        }

        ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>> row = table.get(rowKey);
        if (row == null) {
            return Long.valueOf(0L);
        }

        ConcurrentSkipListMap<String, ConcurrentSet<T>> column = row.get(columnKey);
        if (column == null) {
            return Long.valueOf(0L);
        }

        return column.values().parallelStream().mapToLong(k -> k.size()).sum();
    }

    public void startExpire() {
        executorService.scheduleWithFixedDelay(new Runnable() {

            @Override
            public void run() {
                pruneCache();

            }
        }, 0L, ttl, TimeUnit.HOURS);
    }

    public void closeExpire() {
        executorService.shutdown();
    }

    /**
     * ?
     */
    public void clear() {
        for (String rowKey : table.keySet()) {
            ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>> rowMap = table.get(rowKey);
            for (String columnKey : rowMap.keySet()) {
                ConcurrentSkipListMap<String, ConcurrentSet<T>> columnMap = rowMap.get(columnKey);

                Iterator<String> iterator = columnMap.keySet().iterator();
                while (iterator.hasNext()) {
                    String timesplices = iterator.next();
                    columnMap.get(timesplices).clear();
                    iterator.remove();
                }

            }
            rowMap.clear();
        }

        table.clear();
    }

    private void pruneCache() {
        String expireTime = LocalDateTime.now().minusHours(ttl).format(Util.timeFormatter);
        log.info("{expireTime:{}}", expireTime);

        for (String rowKey : table.keySet()) {
            ConcurrentHashMap<String, ConcurrentSkipListMap<String, ConcurrentSet<T>>> rowMap = table.get(rowKey);
            for (String columnKey : rowMap.keySet()) {
                ConcurrentSkipListMap<String, ConcurrentSet<T>> columnMap = rowMap.get(columnKey);

                Iterator<String> iterator = columnMap.keySet().iterator();
                while (iterator.hasNext()) {
                    String timesplices = iterator.next();
                    if (timesplices.compareTo(expireTime) < 0) {
                        columnMap.get(timesplices).clear();
                        iterator.remove();
                    } else {
                        break;
                    }
                }
            }
        }

    }

    @Override
    public String toString() {
        final String padding = "-----------";

        StringBuilder stringBuilder = new StringBuilder(256);
        table.forEach((row, value) -> {
            stringBuilder.append("row: ").append(row).append(", ");
            value.forEach((colum, value2) -> {
                stringBuilder.append("colum: ").append(colum).append(", ");
                value2.forEach((timesplice, value3) -> {
                    stringBuilder.append("timesplice: [").append(timesplice).append("] ");
                    stringBuilder.append(" values: ").append(value3).append("; ");
                });
                stringBuilder.append("\n").append(padding);
            });
            int index = stringBuilder.lastIndexOf(padding);
            index = index == -1 ? 0 : index;
            stringBuilder.delete(index, stringBuilder.length());
            stringBuilder.append("\n");
        });

        return stringBuilder.toString();
    }

    public static void main(String[] args) throws InterruptedException {
        ConcurrentHashMapBasedTable<Long> table = new ConcurrentHashMapBasedTable<>();
        // table.startExpire();

        table.put("row", "col", LocalDateTime.now().minusHours(4L).format(Util.timeFormatter), Uuid.getId());
        table.put("row", "col", LocalDateTime.now().format(Util.timeFormatter), Uuid.getId());
        table.put("row", "col", LocalDateTime.now().format(Util.timeFormatter), Uuid.getId());
        table.put("row", "col", LocalDateTime.now().format(Util.timeFormatter), Uuid.getId());
        table.put("row", "col", LocalDateTime.now().format(Util.timeFormatter), Uuid.getId());
        table.put("row1", "col", LocalDateTime.now().format(Util.timeFormatter), Uuid.getId());
        table.put("row1", "col2", LocalDateTime.now().format(Util.timeFormatter), Uuid.getId());
        table.put("row", "col", LocalDateTime.now().plusDays(1).format(Util.timeFormatter), Uuid.getId());
        System.out.println(table);
        // System.out.println(table.getSumForRowKey("row"));
        // System.out.println(table.getSumForRowKey("row1"));
        // System.out.println(table.getSumForRowKey("row1s"));
        // System.out.println(table.getSumForRowColumnKey("row", "col"));
        // System.out.println(table.getSumForRowColumnKey("row1", "col"));
        // System.out.println(table.getSumForRowColumnKey("row1", "col2"));
        // table.startExpire();
        // TimeUnit.SECONDS.sleep(5L);
        // table.closeExpire();
        //
        // System.out.println(table);
        // TimeUnit.SECONDS.sleep(5L);
        // List<Long> list = table.get("row", "col", LocalDateTime.now().format(Util.timeFormatter));
        // System.out.println(list);
        //
        // List<Long> list2 = table.get("row", "col");
        // System.out.println(list2);

        table.clear();
        System.out.println("" + table);
    }
}