{"action":"closed","issue":{"url":"https://api.github.com/repos/jankotek/mapdb/issues/370","repository_url":"https://api.github.com/repos/jankotek/mapdb","labels_url":"https://api.github.com/repos/jankotek/mapdb/issues/370/labels{/name}","comments_url":"https://api.github.com/repos/jankotek/mapdb/issues/370/comments","events_url":"https://api.github.com/repos/jankotek/mapdb/issues/370/events","html_url":"https://github.com/jankotek/mapdb/issues/370","id":40319091,"number":370,"title":"I can get the issue again for ArrayIndexOutOfBoundsException on BTreeMap.put","user":{"login":"zshen-talend","id":7779512,"avatar_url":"https://avatars.githubusercontent.com/u/7779512?v=3","gravatar_id":"","url":"https://api.github.com/users/zshen-talend","html_url":"https://github.com/zshen-talend","followers_url":"https://api.github.com/users/zshen-talend/followers","following_url":"https://api.github.com/users/zshen-talend/following{/other_user}","gists_url":"https://api.github.com/users/zshen-talend/gists{/gist_id}","starred_url":"https://api.github.com/users/zshen-talend/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zshen-talend/subscriptions","organizations_url":"https://api.github.com/users/zshen-talend/orgs","repos_url":"https://api.github.com/users/zshen-talend/repos","events_url":"https://api.github.com/users/zshen-talend/events{/privacy}","received_events_url":"https://api.github.com/users/zshen-talend/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/jankotek/mapdb/labels/2.0","name":"2.0","color":"009800"},{"url":"https://api.github.com/repos/jankotek/mapdb/labels/bug","name":"bug","color":"fc2929"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2014-08-15T02:51:28Z","updated_at":"2016-02-14T17:33:35Z","closed_at":"2016-02-14T17:33:35Z","body":"I create DB like that:\r\n<code>\r\ndb = DBMaker.newTempFileDB().sizeLimit(2).mmapFileEnable().deleteFilesAfterClose().cacheSize(10 * 1024).closeOnJvmShutdown().transactionDisable().make();\r\n</code>\r\n\r\nI create TreeMap like that:\r\n<code>\r\ndbMap = db\r\n                .createTreeMap(\"testTupleArrayKeyMap\").nodeSize(6).keySerializer(new TupleArrayKeySerializer(BTreeMap.COMPARABLE_COMPARATOR, BTreeMap.COMPARABLE_COMPARATOR, getDB().getDefaultSerializer(), getDB().getDefaultSerializer())).valueSerializer(Serializer.JAVA).make();//$NON-NLS-1$\r\n</code>\r\nYes, I used my Serializer class which name is TupleArrayKeySerializer.\r\nBecause of I need make the key as List<String> and the length is not certain.\r\n\r\nMy Serializer is as below:\r\n<code>\r\npackage org.talend.commons.MapDB.utils;\r\n\r\nimport java.io.DataInput;\r\nimport java.io.DataOutput;\r\nimport java.io.IOException;\r\nimport java.io.Serializable;\r\nimport java.util.Comparator;\r\n\r\nimport org.mapdb.BTreeKeySerializer;\r\nimport org.mapdb.BTreeMap;\r\nimport org.mapdb.DataInput2;\r\nimport org.mapdb.DataOutput2;\r\nimport org.mapdb.Fun;\r\nimport org.mapdb.Serializer;\r\n\r\npublic final class TupleArrayKeySerializer extends BTreeKeySerializer<Tuple> implements Serializable {\r\n\r\n    private static final long serialVersionUID = 2183804367032891772L;\r\n\r\n    protected final Comparator<Integer> aComparator;\r\n\r\n    protected final Comparator<String> bComparator;\r\n\r\n    protected final Serializer<Integer> aSerializer;\r\n\r\n    protected final Serializer<String> bSerializer;\r\n\r\n    /**\r\n     * Construct new Tuple2 Key Serializer. You may pass null for some value, In that case 'default' value will be used,\r\n     * Comparable comparator and Default Serializer from DB.\r\n     * \r\n     * @param aComparator comparator used for first tuple value\r\n     * @param aSerializer serializer used for first tuple value\r\n     * @param bSerializer serializer used for second tuple value\r\n     */\r\n    public TupleArrayKeySerializer(Comparator<Integer> aComparator, Comparator<String> bComparator,\r\n            Serializer<Integer> aSerializer, Serializer<String> bSerializer) {\r\n        this.aComparator = aComparator;\r\n        this.bComparator = bComparator;\r\n        this.aSerializer = aSerializer;\r\n        this.bSerializer = bSerializer;\r\n    }\r\n\r\n    @Override\r\n    public void serialize(DataOutput out, int start, int end, Object[] keys) throws IOException {\r\n        int acount = 0;\r\n        Integer[] bCount = null;\r\n        if (keys != null && keys[0] != null && keys.length > 0) {\r\n            TupleArray firstTuple = (TupleArray) keys[0];\r\n            bCount = new Integer[firstTuple.arrayLength];\r\n\r\n            for (int i = start; i < end; i++) {\r\n                TupleArray t = (TupleArray) keys[i];\r\n                if (acount == 0) {\r\n                    // write new A\r\n                    aSerializer.serialize(out, t.arrayLength);\r\n                    // count how many A are following\r\n                    acount = 1;\r\n                    while (i + acount < end\r\n                            && aComparator.compare(t.arrayLength, ((TupleArray) keys[i + acount]).arrayLength) == 0) {\r\n                        acount++;\r\n                    }\r\n                    DataOutput2.packInt(out, acount);\r\n\r\n                }\r\n                for (int index = 0; index < t.keyArray.length; index++) {\r\n                    if (bCount[index] == null || bCount[index] == 0) {\r\n                        bSerializer.serialize(out, t.keyArray[index].toString());\r\n                        //\r\n                        bCount[index] = 1;\r\n                        while (i + bCount[index] < end\r\n                                && bComparator.compare(t.keyArray[index], ((TupleArray) keys[i + bCount[index]]).keyArray[index]) == 0) {\r\n                            bCount[index]++;\r\n                        }\r\n                        DataOutput2.packInt(out, bCount[index].intValue());\r\n                    }\r\n                    bCount[index]--;\r\n                }\r\n            }\r\n            acount--;\r\n        }\r\n    }\r\n\r\n    /*\r\n     * (non-Javadoc)\r\n     * \r\n     * @see org.mapdb.BTreeKeySerializer#deserialize(java.io.DataInput, int, int, int)\r\n     */\r\n    @Override\r\n    public Object[] deserialize(DataInput in, int start, int end, int size) throws IOException {\r\n\r\n        Object[] ret = new Object[size];\r\n        try {\r\n            Integer a = null;\r\n            String[] keyArray = null;\r\n            int acount = 0;\r\n            Integer[] bCount = null;\r\n            for (int i = start; i < end; i++) {\r\n                if (acount == 0) {\r\n                    // read new A\r\n                    a = aSerializer.deserialize(in, -1);\r\n                    acount = DataInput2.unpackInt(in);\r\n\r\n                    // init bCount array\r\n                    if (bCount == null) {\r\n                        keyArray = new String[a];\r\n                        bCount = new Integer[a];\r\n                    }\r\n                }\r\n\r\n                for (int index = 0; index < a.intValue(); index++) {\r\n                    if (bCount[index] == null || bCount[index] == 0) {\r\n                        String value = bSerializer.deserialize(in, -1);\r\n                        bCount[index] = DataInput2.unpackInt(in);\r\n                        // if (bCount[index] > 2) {\r\n                        // System.out.println(\"fail\");\r\n                        // }\r\n                        keyArray[index] = value;\r\n                    }\r\n                    bCount[index]--;\r\n                }\r\n                ret[i] = new TupleArray(a, keyArray);\r\n                acount--;\r\n            }\r\n            assert (acount == 0);\r\n\r\n        } catch (IOException e) {\r\n            e.printStackTrace();\r\n        }\r\n        return ret;\r\n    }\r\n\r\n    @Override\r\n    public Comparator<Tuple> getComparator() {\r\n        return BTreeMap.COMPARABLE_COMPARATOR;\r\n    }\r\n\r\n    @Override\r\n    public boolean equals(Object o) {\r\n        if (this == o) {\r\n            return true;\r\n        }\r\n        if (o == null || getClass() != o.getClass()) {\r\n            return false;\r\n        }\r\n\r\n        TupleArrayKeySerializer t = (TupleArrayKeySerializer) o;\r\n\r\n        return Fun.eq(aComparator, t.aComparator) && Fun.eq(bComparator, t.bComparator) && Fun.eq(aSerializer, t.aSerializer)\r\n                && Fun.eq(bSerializer, t.bSerializer);\r\n    }\r\n\r\n    @Override\r\n    public int hashCode() {\r\n        int result = aComparator != null ? aComparator.hashCode() : 0;\r\n        result = 31 * result + (aSerializer != null ? aSerializer.hashCode() : 0);\r\n        result = 31 * result + (aSerializer != null ? aSerializer.hashCode() : 0);\r\n        result = 31 * result + (bSerializer != null ? bSerializer.hashCode() : 0);\r\n        return result;\r\n    }\r\n}\r\n\r\n</code>\r\n\r\nMy issue is that when i used that by 100 thousand items and one item only contain 1 column.\r\nHere i will get a ArrayIndexOutOfBoundsException.\r\n\r\nAnd when i get the exception the all of leafnode will be same as one(null , or some data)"}}