簡體   English   中英

深度復制對性能的影響

[英]performance impact of deep copy

我有一個保存在內存中的復雜對象,不應修改。 它用作模板,在其中首次初始化對象時初始化一些字段,並根據某些調用代碼參數在運行時確定和更新一些字段。

考慮以下示例:

FooTemplate是一個加載到內存中的對象。 調用代碼需要此對象的更新版本。 更新后的版本具有填充的服務中心列表。 列表的內容取決於客戶端代碼中的某些參數,在這種情況下為呼叫者所在的國家。

public class FooTemplate {

    private final String companyName;

    private final String identifier;

    private final List<String> serviceCenters = new ArrayList<String>();

    public FooTemplate(String companyName, String identifier) {
        this.companyName = companyName;
        this.identifier = identifier;
    }

    public String getCompanyName() {
        return companyName;
    }

    public String getIdentifier() {
        return identifier;
    }

    public List<String> getServiceCenters() {
        return serviceCenters;
    }

    @Override
    public String toString() {
        return "FooTemplate [companyName=" + companyName + ", identifier="
                + identifier + ", serviceCenters=" + serviceCenters + "]";
    }       

}

FooManager是一個加載FooTemplate對象的單例:

public class FooManager {

    private static final FooManager fooManager = new FooManager();

    private FooTemplate fooTemplate;

    private FooManager() {      
        this.fooTemplate = new FooTemplate("ABC inc.", "93746789");
    }

    public static FooManager getInstance() {
        return fooManager;
    }

    public FooTemplate getFoo() {
        return fooTemplate;
    }

}

這是測試類:

   class Test {

    public static void main(String[] args) {

        Caller[] callers = {new Caller (CountryCode.US),
                new Caller (CountryCode.US),
                new Caller (CountryCode.US)};

        for (int i = 0; i < callers.length; i++){
        System.out.println(getFoo(callers[i]));
        }

    }

    public static FooTemplate getFoo(Caller caller) {

        FooManager fooManager = FooManager.getInstance();

        FooTemplate fooTemplate = fooManager.getFoo();

        if (caller.getCountryCode() == CountryCode.US){ 
            fooTemplate.getServiceCenters().add("Seattle");
            fooTemplate.getServiceCenters().add("Boston");
        }
        if (caller.getCountryCode() == CountryCode.GER){    
            fooTemplate.getServiceCenters().add("Munich");
            fooTemplate.getServiceCenters().add("Berlin");
        }
        if (caller.getCountryCode() == CountryCode.FRA){    
            fooTemplate.getServiceCenters().add("Paris");
            fooTemplate.getServiceCenters().add("Lyon");
        }   

        return fooTemplate;

    }
}

它產生以下輸出:

FooTemplate [companyName = ABC inc。,標識符= 93746789,serviceCenters = [西雅圖,波士頓]]

FooTemplate [companyName = ABC inc。,標識符= 93746789,serviceCenters = [西雅圖,波士頓,西雅圖,波士頓]]

FooTemplate [companyName = ABC inc。,標識符= 93746789,serviceCenters = [西雅圖,波士頓,西雅圖,波士頓,西雅圖,波士頓]]

我知道發生這種情況是因為同一對象在每次迭代中都會被修改。 在修改對象並返回副本之前,是否需要對對象進行深層復制,還是有更好的解決方案?

編輯:在實際的代碼中,模板對象是通過解析xml創建的,僅在單例中解析一次。 這就是為什么我不能在每次需要時都創建一個新的模板對象。

您可以在每次調用getFoo時創建一個新的FooTemplate實例。

public static FooTemplate getFoo() {
    return new FooTemplate("ABC inc.", "93746789");
}

或者,如果您不想創建太多companyNameidentifier ,請考慮調用String.intern() (我認為編譯器仍然會優化內存分配。)

如果兩個字符串在整個程序中都是常量,請考慮將它們聲明為static final

通常,從另一個對象復制對象不是一個好習慣,而您可以從頭開始創建它們。

編輯:只需創建一個新類FooCompany

public class FooCompany {

    private final String companyName;

    private final String identifier;

    public FooCompany(String companyName, String identifier) {
        this.companyName = companyName;
        this.identifier = identifier;
    }

    public String getCompanyName() {
        return companyName;
    }

    public String getIdentifier() {
        return identifier;
    }
}


public class FooManager {

    private static final FooManager fooManager = new FooManager();

    private FooCompany fooCompany;

    private FooManager() {      
        this.fooCompany = new FooCompany("ABC inc.", "93746789");
    }

    public static FooManager getInstance() {
        return fooManager;
    }

    public FooTemplate getFoo() {
        return new FooTemplate(fooCompany.getCompanyName(), fooCompany.getIdentifier());
    }

}

//您可以使用以下代碼替換FooManger

公共類FooManager {

private static final FooManager fooManager = new FooManager();
//if company and contact are fix, make them final
private final String COMPANY="ABC inc.";
private final String CONTACT="93746789";

private FooManager() {      

}

public static FooManager getInstance() {
    return fooManager;
}

public FooTemplate getFoo() {
    return new FooTemplate(COMPANY, CONTACT);
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM