Java 如何使用GSON将大型JSON文件分割成块并进行排序

Java 如何使用GSON将大型JSON文件分割成块并进行排序,java,json,sorting,parsing,gson,Java,Json,Sorting,Parsing,Gson,我有一个巨大的JSON文件名为something.JSON。文件大小为20MB。我正在和格森一起读这篇文章。它是在标准安卓Nexus 5X上读取的 Json的示例: [ {"country":"UA","name":"Hurzuf","_id":707860,"coord":{"lon":34.283333,"lat":44.549999}}, {"country":"UA","name":"Il’ichëvka","_id":707716,"coord":{"lon":34.3

我有一个巨大的JSON文件名为something.JSON。文件大小为20MB。我正在和格森一起读这篇文章。它是在标准安卓Nexus 5X上读取的

Json的示例:

[
    {"country":"UA","name":"Hurzuf","_id":707860,"coord":{"lon":34.283333,"lat":44.549999}},
    {"country":"UA","name":"Il’ichëvka","_id":707716,"coord":{"lon":34.383331,"lat":44.666668}},
    {"country":"BG","name":"Rastnik","_id":727762,"coord":{"lon":25.283331,"lat":41.400002}}
...
]
代码:

它需要从Android API 16运行到最新版本

我需要把这个读给McCities,然后按城市名称的字母顺序排序。现在这需要3分钟,必须在10秒内完成。我的方法是将json文件分成10个较小的块,读入,连接并排序

所以我的问题是:如何将文件分成更小的块,这是解决这个问题的正确方法吗


链接到文件:

我基本上从来没有做过Android本身的编码,但我有一些注释和想法供您参考,因为这是纯Java。 您的读者在阅读每一个元素时都做了大量的工作。 首先,您不需要每次需要时都创建
Gson

  • 它是不可变的,线程安全的
  • 这是相对昂贵的创建
  • 实例化一个
    Gson
    实例也会命中堆,需要花费更多的时间来执行,然后进行垃圾收集
接下来,Gson中仅反序列化和JSON流读取之间有一个区别:第一个可能会在后台使用重类型适配器组合,而后者只需逐个令牌解析JSON文档。 话虽如此,您可以在读取JSON流时获得更好的性能:众所周知,您的JSON文件具有非常严格的结构,因此可以更简单地实现高级解析器

假设一个简单的测试套件,针对您的问题有不同的实现:

数据对象 City.java
最后一级城市{
@SerializedName(“\u id”)
最终int id;
@序列化名称(“国家”)
最终字符串国家;
@序列化名称(“名称”)
最后的字符串名;
@序列化名称(“协调”)
最终坐标;
私人城市(最终整数id、最终字符串国家、最终字符串名称、最终坐标){
this.id=id;
这个国家=国家;
this.name=名称;
这个。坐标=坐标;
}
静态城市(最终整数id、最终字符串国家、最终字符串名称、最终坐标){
返回新城市(id、国家、名称、坐标);
}
@凌驾
公共布尔等于(最终对象o){
if(this==o){
返回true;
}
如果(o==null | | getClass()!=o.getClass()){
返回false;
}
最终城市,即=(城市)o;
return id==that.id;
}
@凌驾
公共int hashCode(){
返回id;
}
@抑制警告(“恒定条件”)
公共静态int compareByName(最终城市1,最终城市2){
返回city1.name.compareTo(city2.name);
}
}
Coordinates.java
最终类坐标{
@序列化名称(“lat”)
最终双纬度;
@序列化名称(“lon”)
最终双经度;
专用坐标(最终双纬度、最终双经度){
这个。纬度=纬度;
这个经度=经度;
}
静态坐标(最终双纬度、最终双经度){
返回新坐标(纬度、经度);
}
@凌驾
公共布尔等于(最终对象o){
if(this==o){
返回true;
}
如果(o==null | | getClass()!=o.getClass()){
返回false;
}
最终坐标=(坐标)o;
返回Double.compare(即纬度,纬度)==0
&&比较(即经度,经度)==0;
}
@凌驾
公共int hashCode(){
最终长纬度EBITs=双倍。双倍至长位(纬度);
最终长纵向比特率=双精度。双精度长比特率(经度);
最终int latitudeHash=(int)(latitudeBits^ latitudeBits>>>32);
最终int longitudeHash=(int)(longitudeBits^ longitudeBits>>>32);
返回31*latitudeHash+LongtudeHash;
}
}
测试基础设施 ITest.java
接口测试{
@非空
默认字符串getName(){
返回getClass().getSimpleName();
}
@非空
集合测试(@Nonnull JsonReader-JsonReader)
抛出IOException;
}
主要的
publicstaticvoidmain(最终字符串…args)
抛出IOException{
最终Iterable测试=不可变列表(
FirstTest.get(),
ReadAsWholeListTest.get(),
ReadAsWholeTreeSetTest.get(),
ReadJsonStreamIntoListTest.get(),
readjsonstreamnotreesettest.get(),
ReadJsonStreamIntoListChunksTest.get()
);
对于(int i=0;i<3;i++){
用于(最终ITest测试:测试){
try(final-ZipInputStream-ZipInputStream=new-ZipInputStream(Resources.getPackageResourceInputStream(Q49273660.class,“cities.json.zip”)){
for(ZipEntry-ZipEntry=zipInputStream.getnextery();ZipEntry!=null;ZipEntry=zipInputStream.getnextery()){
if(zipEntry.getName().equals(“cities.json”)){
final JsonReader JsonReader=new JsonReader(new InputStreamReader(zipInputStream));//不关闭
System.out.printf(“%1$35s:”,test.getName());
final Stopwatch Stopwatch=Stopwatch.createStarted();
最终收集城市=test.test(jsonReader);
System.out.printf(“以%d毫秒为单位,包含%d个元素\n”、stopwatch.appead(TimeUnit.ms)、cities.size());
资产排序(城市,城市::compareByName);
}
}
@Override
protected ArrayList<City> doInBackground(File... files) {
    ArrayList<City> cities = new ArrayList<>();
    try {
        InputStream is = new FileInputStream(files[0]);
        JsonReader reader = new JsonReader(new InputStreamReader(is, "UTF-8"));
        reader.beginArray();
        while (reader.hasNext()) {
            City city = new Gson().fromJson(reader, City.class);
            cities.add(city);
        }
        reader.endArray();
        reader.close();
    } catch (Exception e) {
        mResult.onFinish(cities, e.getMessage());
    }

    Collections.sort(cities, (o1, o2) -> o1.getName().compareTo(o2.getName()));
    mResult.onFinish(cities, CityService.SUCCESS);
    return cities;
}
com.google.code.gson:gson:2.8.0
final class ReadAsWholeTreeSetTest
        implements ITest {

    private static final ITest instance = new ReadAsWholeTreeSetTest();

    private ReadAsWholeTreeSetTest() {
    }

    static ITest get() {
        return instance;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private static final TypeToken<TreeSet<?>> rawTreeSetType = (TypeToken) TypeToken.get(TreeSet.class);

    private static final Map<Type, Comparator<?>> comparatorsRegistry = ImmutableMap.of(
            City.class, (Comparator<City>) City::compareByName
    );

    private static final Gson gson = new GsonBuilder()
            .registerTypeAdapterFactory(new TypeAdapterFactory() {
                @Override
                public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
                    if ( !TreeSet.class.isAssignableFrom(typeToken.getRawType()) ) {
                        return null;
                    }
                    final Type elementType = ((ParameterizedType) typeToken.getType()).getActualTypeArguments()[0];
                    @SuppressWarnings({ "rawtypes", "unchecked" })
                    final Comparator<Object> comparator = (Comparator) comparatorsRegistry.get(elementType);
                    if ( comparator == null ) {
                        return null;
                    }
                    final TypeAdapter<TreeSet<?>> originalTreeSetTypeAdapter = gson.getDelegateAdapter(this, rawTreeSetType);
                    final TypeAdapter<?> originalElementTypeAdapter = gson.getDelegateAdapter(this, TypeToken.get(elementType));
                    final TypeAdapter<TreeSet<Object>> treeSetTypeAdapter = new TypeAdapter<TreeSet<Object>>() {
                        @Override
                        public void write(final JsonWriter jsonWriter, final TreeSet<Object> treeSet)
                                throws IOException {
                            originalTreeSetTypeAdapter.write(jsonWriter, treeSet);
                        }

                        @Override
                        public TreeSet<Object> read(final JsonReader jsonReader)
                                throws IOException {
                            jsonReader.beginArray();
                            final TreeSet<Object> elements = new TreeSet<>(comparator);
                            while ( jsonReader.hasNext() ) {
                                final Object element = originalElementTypeAdapter.read(jsonReader);
                                elements.add(element);
                            }
                            return elements;
                        }
                    }.nullSafe();
                    @SuppressWarnings({ "rawtypes", "unchecked" })
                    final TypeAdapter<T> castTreeSetTypeAdapter = (TypeAdapter<T>) treeSetTypeAdapter;
                    return castTreeSetTypeAdapter;
                }
            })
            .create();

    private static final Type citiesSetType = new TypeToken<TreeSet<City>>() {
    }.getType();

    @Nonnull
    @Override
    public Set<City> test(@Nonnull final JsonReader jsonReader) {
        return gson.fromJson(jsonReader, citiesSetType);
    }

}
                          FirstTest : in 5797 ms with 209557 elements
                ReadAsWholeListTest : in 796 ms with 209557 elements
             ReadAsWholeTreeSetTest : in 733 ms with 162006 elements
         ReadJsonStreamIntoListTest : in 461 ms with 209557 elements
      ReadJsonStreamIntoTreeSetTest : in 452 ms with 162006 elements
   ReadJsonStreamIntoListChunksTest : in 607 ms with 209557 elements
--------------------
                          FirstTest : in 3396 ms with 209557 elements
                ReadAsWholeListTest : in 493 ms with 209557 elements
             ReadAsWholeTreeSetTest : in 520 ms with 162006 elements
         ReadJsonStreamIntoListTest : in 385 ms with 209557 elements
      ReadJsonStreamIntoTreeSetTest : in 377 ms with 162006 elements
   ReadJsonStreamIntoListChunksTest : in 540 ms with 209557 elements
--------------------
                          FirstTest : in 3448 ms with 209557 elements
                ReadAsWholeListTest : in 429 ms with 209557 elements
             ReadAsWholeTreeSetTest : in 421 ms with 162006 elements
         ReadJsonStreamIntoListTest : in 400 ms with 209557 elements
      ReadJsonStreamIntoTreeSetTest : in 385 ms with 162006 elements
   ReadJsonStreamIntoListChunksTest : in 480 ms with 209557 elements
--------------------