LinkedHashMap中的LinkedHashSet

时间:2016-10-09 21:59:39

标签: java elasticsearch

我有以下格式的JSON响应,我将解析它以获取每个键的键(key_as_String)和值(Expected_Usage和Actual_Usage)。

"aggregations": {
    "Inner_aggregation": {
        "doc_count": 366,
        "Hours_aggregation": {
            "doc_count": 366,
            "by_day": {
                "buckets": [
                    {
                        "key_as_string": "2016-01-11",
                        "key": 1452556800000,
                        "doc_count": 1,
                        "Expected_Usage": {
                            "value": 5
                        },
                        "Actual_Usage": {
                            "value": 3
                        }
                    },
                    {
                        "key_as_string": "2016-01-12",
                        "key": 1452556800000,
                        "doc_count": 1,
                        "Expected_Usage": {
                            "value": 43
                        },
                        "Actual_Usage": {
                            "value": 2
                        }
                    },
                    .........,
                    .........
                ]
            }
        }
    }
}
}

我想保留插入顺序,因为Elastic Search返回的KEYS已经排序。我还想保持每个键的VALUES顺序。

考虑使用LinkedHashmap和LinkedHashSet。

LinkedHashMap<String, LinkedHashSet<Integer>> LinkedMap = 
              new LinkedHashMap<String,LinkedHashSet<Integer>>();

LinkedHashSet<Integer> LinkedSet = 
                      new LinkedHashSet<Integer>(); 
LinkedSet.add(3);
LinkedSet.add(4);
LinkedSet.add(2);

LinkedMap.put("2016/03/11",LinkedSet);


for(Map.Entry m:LinkedMap.entrySet()){
   System.out.println("Key is : " + m.getKey() + " Values: " + m.getValue());
  }

在内存和性能方面有更好的选择吗?

2 个答案:

答案 0 :(得分:2)

有很多选择,主要取决于您将如何使用所获取的数据 - 例如如果您不关心修改数据的调用代码,那么使用公共成员设计结构将导致CPU压力最小。

  

响应中的最大可能键值为365,每个键只有2个值。

我明白了。我建议删除LinkedHashSet并编写自定义类来保存这两个整数未装箱(在将int转换为Integer并返回时不要浪费CPU):< / p>

public class ExpectedVsActual {
  // if you don't care too much of your data integrity
  // along other lines of coding, make those public
  // and forget about getters
  protected int expected;
  protected int actual;

  public ExpectedVsActual(int exp, int act) {
    this.expected=exp;
    this.actual=act;
  }
  public int getExpected() {
    return this.expected;
  }
  public int getActual() {
     return this.actual;
  }
}

然后

LinkedHashMap<String, ArrayList<ExpectedVsActual>> myMap=...; // etc

当然,如果你不需要搜索键,那么你就不需要地图了。

如果您想要每个键的单独条目,也许最好将每个条目包装为结构:

public class MyEntryRepresentation {
   protected String dateStr;

   // ArrayList: faster iteration by position
   // LinkedList: memory conservative - doesn't allocate more than necessary
   protected List<ExpectedVsActual> data;

   public MyEntryRepresentation(String date) 
     this.dateStr=date;
     this.data=new ArrayList<ExpectedVsActual>();
   }

   public void addEntry(int expected, int actual) {
     this.data.add(new ExpectedVsActual(expected, actual));
   }

   public List<ExpectedVsActual> getValues() {
     // if you don't care what the caller will do with your List 
     return this.data;
     // If you want to forbid them to modify the returned list
     // return Collections.unmodifiableList(this.data);
   }

   public String getDateStr() {
     return this.date;
   }
} 

然后

LinkedHashMap<String, MyEntryRepresentation> map=... etc;

map.add(entry.getDateStr(), entry);

答案 1 :(得分:1)

linkedhashmap在里面使用一个Entry Array,无论你把一个新值放到地图中,都会创建一个新的Entry,新的Entry可以引用前一个条目。另外,我不建议使用set,因为如果Expected_Usage和Actual_Usage之间有相同的值,则集合中将有一个值。我创建了一个简单的数据结构来解决您的问题,希望这可以提供帮助。

Sending build context to Docker daemon    20 MB
Step 0 : FROM alpine:3.4
 ---> ad84c222f6a3
Step 1 : RUN apk upgrade --update     && apk add libatomic readline readline-dev libxml2 libxml2-dev         libxslt libxslt-dev zlib-dev zlib ruby yaml         yaml-dev libffi-dev build-base git nodejs         ruby-io-console ruby-irb ruby-json ruby-rake         make gsl gsl-dev         gcc g++ libffi-dev ruby-dev tzdata
 ---> Using cache
 ---> b7f66d6f2bd7
Step 2 : RUN gsl-config --cflags
 ---> Using cache
 ---> b5acc8868a74
Step 3 : RUN gem install --no-document nmatrix gsl
 ---> Using cache
 ---> 2623683a706e
Step 4 : ADD scripts/gsl-test.rb test.rb
 ---> e4388f952198
Removing intermediate container 743340a3be60
Step 5 : RUN ruby test.rb
 ---> Running in c53a34ece153
/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': Error relocating /usr/lib/ruby/gems/2.3.0/gems/gsl-2.1.0.1/lib/gsl_native.so: gsl_multifit_fdfsolver_jac: symbol not found - /usr/lib/ruby/gems/2.3.0/gems/gsl-2.1.0.1/lib/gsl_native.so (LoadError)
        from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /usr/lib/ruby/gems/2.3.0/gems/backports-3.6.8/lib/backports/std_lib.rb:9:in `require_with_backports'
        from /usr/lib/ruby/gems/2.3.0/gems/gsl-2.1.0.1/lib/gsl.rb:11:in `<top (required)>'
        from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `require'
        from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `rescue in require'
        from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:40:in `require'
        from test.rb:1:in `<main>'
The command '/bin/sh -c ruby test.rb' returned a non-zero code: 1