-8

Source

public class TestingPointers {

    private String a;
    private static String b = "b";
    private String c;
    private static String all = intensiveProcess(); //It would be preferable if the intensiveProcess() method only had to be run once.

    public static void main(String args[]) {
        System.out.println(all);
        b = "z";
        System.out.println(all);
    }

    public String intensiveProcess() {
       String out = "";
       for (int i = 0; i < 25000000000000; i++) {
          //a = random words
          out += a;
       }
       out += b;
       for (int i = 0; i < 25000000000000; i++) {
          //c = random words
          out += c;
       }
       return out;
    }
}

Output

RandomWords-b-RandomWords
RandomWords-b-RandomWords

Desired Output

RandomWords-b-RandomWords
RandomWords-z-RandomWords

Question

Is there a way to update all without having to reassign a and c each time b is updated? i.e. all should point to b as opposed to containing its value itself.

ThreaT
  • 3,683
  • 14
  • 61
  • 103
  • 4
    Basically: no, there isn't. If you could provide more context, we may be able to suggest an alternative solution. – Jon Skeet Aug 14 '15 at 15:12
  • 3
    I doubt it. You want a concatenated string, but you don't want to perform string concatenation... You say "Imagine that a + b is an expensive calculation... but we know that it's string concatenation." It's really unclear what you mean here... – Jon Skeet Aug 14 '15 at 15:22
  • @ThreaT and you decided, that this information about couting to 50 tryllion is not imortant for question? – m.cekiera Aug 14 '15 at 15:28
  • 2
    @Threat: Then your question is misleading, and should be updated. You're not updating a string, you're updating something which can be converted to a string, but *that* is expensive. Again, we need more context in order to help you. Your simplification has just confused things. – Jon Skeet Aug 14 '15 at 15:28
  • Well it's still not clear, to be honest - it's not obvious how you'd expect that to *possibly* work. When you update a value in your *real* code, does that involve a lot of calculations? Can you store some partial results and perform only the relevant changes? – Jon Skeet Aug 14 '15 at 16:15
  • @ThreaT: Well it sounds like there may be better approaches possible, but we can't tell without more context... even the updated question doesn't sound like it's *really* representative. – Jon Skeet Aug 14 '15 at 16:17
  • @ThreaT Strings are immutable by the way – Blake Yarbrough Aug 14 '15 at 16:21
  • @ThreaT: Well there's simply no way of doing that with strings in Java. You can't make the middle of a string refer to some other variable. Now you can write your own class which saves all the calculations and remembers the `b` value, then builds a string each time it *needs* to, only recomputing what is required... but I don't know whether or not that would meet your requirement... – Jon Skeet Aug 14 '15 at 16:24
  • See http://stackoverflow.com/questions/1552301/immutability-of-strings-in-java – Blake Yarbrough Aug 14 '15 at 16:25
  • 1
    @ThreaT: Well, good luck with it - but I don't think it's *actually* going to solve your problem at all. – Jon Skeet Aug 14 '15 at 16:31

2 Answers2

0

Revised

Because strings are immutable their references aren't copied. To get around this you can use a StringBuffer, but because you want to update a string and have it reflect on another string, your going to need to do some encapsulation of the StringBuffer's to accomplish it.

class StringChain  {

    private StringBuffer[] buffers;

    public StringChain(StringBuffer[] buffers) {
        this.buffers = buffers;
    }

    public String toString() {
        String finalStr = "";
        for (StringBuffer buf : buffers)
            finalStr += buf;
        return finalStr;
    }
}

And then you can create that object and add StringBuffer's to it. When you want to get the entire string call the toString method

public static void main(String []args){
    StringBuffer a = new StringBuffer("a"); //Create StringBuffer a
    StringBuffer b = new StringBuffer("b"); //Create StringBuffer b
    StringChain chain = new StringChain(new StringBuffer[] { a, b }); //Pass both buffers to the String Chain
    System.out.println(chain);
    setStringBufferValue(b, "c");
    System.out.println(chain);
 }
 
 private static void setStringBufferValue(StringBuffer buf, String value) {
     buf.replace(0, buf.length(), value);
 }

This will print:

ab

ac

Here is the StringBuilder alternative which is generally recommended over StringBuffer. All that needs to be done is to replace the StringBuffer will StringBuilder instead.

class StringChain  {

    private StringBuilder[] builders;

    public StringChain(StringBuilder[] builders) {
        this.builders = builders;
    }

    public String toString() {
        String finalStr = "";
        for (StringBuilder b : builders)
            finalStr += b;
        return finalStr;
    }
}

....

public static void main(String []args){
    StringBuilder a = new StringBuilder("a"); //Create StringBuilder a
    StringBuilder b = new StringBuilder("b"); //Create StringBuilder b
    StringChain chain = new StringChain(new StringBuilder[] { a, b }); //Pass both builders to the String Chain
    System.out.println(chain);
    setStringBuilderValue(b, "c");
    System.out.println(chain);
 }
 
 private static void setStringBuilderValue(StringBuilder b, String value) {
     b.replace(0, b.length(), value);
 }
Community
  • 1
  • 1
Jmrapp
  • 522
  • 4
  • 12
  • I misunderstood the explanation. Let me edit my answer with an actual solution – Jmrapp Aug 14 '15 at 15:21
  • I have revised this answer, the last comment was an accident @ThreaT – Jmrapp Aug 14 '15 at 15:33
  • Its the StringBuffer type. The StringBuffer is essentially an encapsulation around a string to allow you to pass a string reference around instead of copying the value. A String is an immutable data type which means that when you set it's value to another string it copies the object and passes it on, losing the reference to the original. That is why when you set a new value to a string it wont update the others that referenced it earlier because they dont have the original reference. – Jmrapp Aug 14 '15 at 15:34
  • Note that unless synchronization is required, StringBuilder is generally preferred over StringBuffer. And no, setting a string variable to another value doesn't "copy the object and pass it on" - nor is StringBuffer an "encapsulation around a string"... – Jon Skeet Aug 14 '15 at 16:15
  • Yes StringBuilder is generally required, I should have mentioned that. With regards to my explanation of what StringBuffer does, I wanted to make it as simple as possible to understand without having to get into too much of the technicalities of it. Those technicalities are for a whole different discussion. @JonSkeet – Jmrapp Aug 14 '15 at 16:24
  • 1
    @baseball435 If you were going for simple, it seems the simplest way to be the most correct without too much explanation is to simply use `StringBuilder` in the example in lieu of `StringBuffer` – Blake Yarbrough Aug 14 '15 at 16:29
  • @LanguidSquid They both accomplish the task that ThreaT is trying to accomplish so, unless he is worrying about other more technical issues having to do with synchronization and efficiency, which it seems he's not, I think that StringBuffer will work just fine in the same manner that StringBuilder would for this situation. – Jmrapp Aug 14 '15 at 16:41
-2

Use a method to return the concatenation?

public static getAll() {
    return a + b:
}
The Head Rush
  • 2,821
  • 2
  • 24
  • 42