序列化 Collat​​or 实例

Posted

技术标签:

【中文标题】序列化 Collat​​or 实例【英文标题】:Serializing Collator instance 【发布时间】:2012-01-10 20:59:51 【问题描述】:

我正在尝试序列化机构ResultView 类的一些对象,它基本上是guava's TreeMultimap 的包装器:

import java.io.Serializable;
import java.text.Collator;
import java.util.Comparator;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.Maps.EntryTransformer;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Ordering;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;

public class InstitutionResultView implements Serializable 
  private static final long serialVersionUID = -8110992296090587657L;

  private final SortedSetMultimap<String, Institution> nameToInstitutionsMapping = TreeMultimap.create(
      Ordering.from(StringComparators.AS_IS), // insertion order
      Ordering.natural() // <----- this works when serializing object
      // Ordering.from(Collator.getInstance()) // <----- when used instead previous line gives an exception when serializing
          .nullsFirst().onResultOf(StringInstitutionFunctions.BY_NAME) // sort by name
          .compound(
              Ordering.natural().nullsFirst().onResultOf(IntegerInstitutionFunctions.BY_ID) // sort by id
              ));

  public SortedSetMultimap<String, Institution> institutions() 
    return nameToInstitutionsMapping;
  

  public void setInstitutions(final Multimap<String, Institution> institutions) 
    this.nameToInstitutionsMapping.clear();
    this.nameToInstitutionsMapping.putAll(institutions);
  

  @Override
  public String toString() 
    return Objects.toStringHelper(this)
        .add("nameToInstitutionsMapping", Multimaps.transformEntries(nameToInstitutionsMapping, EntryTransformers.TO_NAME_WITH_CATEGORY))
        .toString();
  

在序列化过程中出现异常:

java.io.NotSerializableException: java.text.RuleBasedCollat​​or at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164) 在

...

com.google.common.collect.TreeMultimap.writeObject(TreeMultimap.java:180)

...

我发现this bug from Sun's bug database 涵盖了与我的情况非常相似的情况,但它没有指向任何解决方案。我尝试添加瞬态 Collat​​or 实例字段:

  private transient Collator collatorInstance = Collator.getInstance();

并将其用作Ordering.from(collatorInstance),但仍然不起作用。

如果有人能告诉我如何解决这个问题,我会很高兴。


编辑 - 这对我有用(感谢@Puce 和他的回答):

  class CollatorWrapper implements Comparator<String>, Serializable 
    private static final long serialVersionUID = 1L;

    private transient Collator collatorInstance;

    public CollatorWrapper() 
      super();
      initCollatorInstance();
    

    @Override
    public int compare(final String o1, final String o2) 
      return collatorInstance.compare(o1, o2);
    

    private void initCollatorInstance() 
      collatorInstance = Collator.getInstance();
    

    private void writeObject(final java.io.ObjectOutputStream out) throws IOException 
      out.defaultWriteObject();
    

    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException 
      in.defaultReadObject();
      initCollatorInstance();
    
  

【问题讨论】:

但是请注意,如果您不存储区域设置,如果 jvm 序列化对象和 jvm 反序列化对象具有不同的默认区域设置,您将获得不同的行为。也许这就是你想要的,不过,我只是想指出这一点。 我知道这一点,我已经使用 Locale 参数实现了 Collat​​orWrapper,但在这里我只想展示这个问题的解决方案的本质:) 我不肯定,但我认为您可以通过直接声明私有瞬态 Collat​​or collat​​orInstance = Collat​​or.getInstance() 来避免“initCollat​​orInstance”的尴尬。 @LouisWasserman 是的,我也这么认为 【参考方案1】:

我想你也许可以写一个包装器,它

实现比较器 实现 Serialzable(以及必要的方法,如 readObject、writeObject) 包装一个瞬态整理器 记住区域设置(如果需要)

【讨论】:

以上是关于序列化 Collat​​or 实例的主要内容,如果未能解决你的问题,请参考以下文章

python Collat​​z序列

python 最长的Collat​​z序列(Euler#14)

javascript INTL-collat​​or.js

使用 Java Collat​​or 区分大小写的顺序

HuggingFace:使用自定义 data_loader 和 data_collat​​or 从本地目录流式传输数据集

使用Newtonsoft.Json.dll序列化和反序列化