Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / June 2005

Tip: Looking for answers? Try searching our database.

Question about clone a Hashtable

Thread view: 
George George - 15 May 2005 10:49 GMT
Hello everyone,

I want to clone the content of a Hashtable (its keys, its values and its
key-value relationship). But I have found that the clone method can not
completely clone a Hashtable, as is mentioned in the description of clone
method of Java API Specification,

Creates a shallow copy of this hashtable. All the structure of the
hashtable itself is copied, but the keys and values are not cloned. This is
a relatively expensive operation.

I am wondering what is the efficient and effective approach of cloning a
Hashtable, including the clone of its keys, its values and its key-value
relationship.

Thanks in advance,
George
ByteCoder - 15 May 2005 11:58 GMT
> Hello everyone,
>
[quoted text clipped - 13 lines]
> Thanks in advance,
> George

Perhaps something like this would work (correct me if I'm wrong):

HashTable clone = originalHashTable;

Signature

-------------
- ByteCoder -           ...I see stupid people
-------------
                  Curiosity *Skilled* the cat

Tony Morris - 15 May 2005 12:23 GMT
> > Hello everyone,
> >
[quoted text clipped - 17 lines]
>
> HashTable clone = originalHashTable;

Yes, that is wrong. It will perform a reference assignment, and nothing
more.
Cloning a Hashtable is indicative of something seriously broken, and due to
the common misconception to the contrary, I won't bother justifying the
assertion for fear of boring, useless internet arguments.

Signature

Tony Morris
Software Engineer, IBM Australia.
BInfTech, SCJP 1.4, SCJP 5.0, SCJD

http://www.jtiger.org/ JTiger Unit Test Framework for Java
http://qa.jtiger.org/ Java Q&A (FAQ, Trivia)
http://xdweb.net/~dibblego/

ByteCoder - 15 May 2005 14:11 GMT
>> > Hello everyone,
>> >
[quoted text clipped - 24 lines]
> justifying the assertion for fear of boring, useless internet
> arguments.

Thank you for pointing that out to me. So you're actually saying there
is no really no proper way to clone a HashSet?

Actually, you could create a new HastSet and copy each item from the old
HashSet to the new one. Granted, it's not as fast as 'cloning' it, but
it should work.

Signature

-------------
- ByteCoder -           ...I see stupid people
-------------
                  Curiosity *Skilled* the cat

George George - 16 May 2005 07:57 GMT
Thanks Tony,

I have written a simple sample below, but from the sample's output, I have
found out that it seems that the clone method of Hashtable copies the the
content of both keys and values, not as mentioned in the Java API
specification of clone method of class Hashtable "but the keys and values
are not cloned".

Do you know what points do the Java specification mean?

[Code]
        Hashtable table1 = new Hashtable();
        table1.put ("key1", "value1");
        Hashtable table2 = (Hashtable) table1.clone();
        if (table2.containsKey ("key1"))
        {
            System.out.println ("Contains!");
            table2.put ("key1", "value2");
            String newValue1 = (String) table1.get ("key1");
            System.out.println ("New value1 of table1: " + newValue1);
            newValue1 = (String) table2.get ("key1");
            System.out.println ("New value1 of table2: " + newValue1);
        }
        else
        {
            System.out.println ("Not contains!");
        }
[/Code]

Output is:

Contains!
New value1 of table1: value1
New value1 of table2: value2

regards,
George
G Winstanley - 09 Jun 2005 02:48 GMT
> Thanks Tony,
>
[quoted text clipped - 33 lines]
> regards,
> George

The clone() method creates new references to the same objects that are used
as keys/values for the original. All you are achieving is assigning a
different object to the same key.

Forgive my poor ASCII art, but this is roughly what I mean:

Original
--------
Hashtable1
    Key1 -------------> "key1" <------
    Value1 -----------> "value1" <-  |
Hashtable2                            |  |
    Key1 -------------------------)---
    Value1 -----------------------

Modified
--------
Hashtable1
    Key1 -------------> "key1" <------
    Value1 -----------> "value1"     |
Hashtable2                               |
    Key1 -----------------------------
    Value1 -----------> "value2"

Stan
George George - 09 Jun 2005 08:49 GMT
Thanks Stan,

>> Thanks Tony,
>>
[quoted text clipped - 27 lines]
>
>Stan

What do you mean "All you are achieving is assigning a different object to
the same key"? Could you please provide a sample program to illustrate your
idea?

regards,
George
G Winstanley - 10 Jun 2005 13:18 GMT
> Thanks Stan,
>
[quoted text clipped - 36 lines]
> regards,
> George

Sure. This illustrates a bit of both...

import java.util.*;

public class HashCloneTest
{
   public static void main(String[] args)
   {
       Hashtable table1 = new Hashtable();
       Thing x = new Thing(1);
       table1.put("key", x);
       System.out.println("table1: " + table1.get("key"));

       Hashtable table2 = (Hashtable)table1.clone();
       System.out.println("table2: " + table2.get("key"));

       ((Thing)table1.get("key")).setNum(2);
       System.out.println("table1: " + table1.get("key"));
       System.out.println("table2: " + table2.get("key"));

       table2.put("key", new Thing(3));
       System.out.println("table2: " + table2.get("key"));
   }
   
   private static final class Thing
   {
       private int num;
       private Thing(int i) { setNum(i); }
       private void setNum(int i) { this.num = i; }
       public String toString() { return "Thing[" + num + "]"; }
   }
}

Stan
George George - 12 Jun 2005 12:45 GMT
Thanks Stan,

>> Thanks Stan,
>>
[quoted text clipped - 36 lines]
>
>Stan

Your sample is very helpful. I think in your sample you mean the clone
method of Hashtable only copies the reference of value objects from the
original Hashtable to the new cloned Hashtable, and do not create new
objects for value objects in a new cloned Hashtable. Am I correct?

regards,
George
G Winstanley - 14 Jun 2005 03:50 GMT
> Thanks Stan,
>
[quoted text clipped - 46 lines]
> regards,
> George

Yes, that's what I mean. This system of shallow-copying is done is many
places in the JDK/JRE, notably in the Collection classes. Implementations of
deep-cloning (other than esoteric implementations like Serialization) need
to be hand-crafted by those who desire it.

Stan
George George - 15 Jun 2005 03:53 GMT
Thanks Stan,

>> Thanks Stan,
>>
[quoted text clipped - 8 lines]
>
>Stan

Your reply is very helpful. Why do you say the implementation of
Serialization is esoteric? I am very interested in how Serialization
implements deep-cloning. Could you please describe how deep-cloning of
Serialization is working, or recommend me some online resources (tutorials or
papers) dealing with this topic?

regards,
George
G Winstanley - 17 Jun 2005 01:14 GMT
> Thanks Stan,
>
[quoted text clipped - 19 lines]
> regards,
> George

It simply goes way beyond the scope of the deep-cloning most users need for
everyday purposes. Most programmers will simply need to implement
deep-cloning as far as their application requires, which is often reasonably
simple. Serialization requires compatability with almost every class out
there, and rigorous circularity checking, and version control, etc. so is
esoteric in the sense that it's beyond the simple implementation most will
require. If you're really interested in it's implementation go and look at
the source. java.io.ObjectOutputStream.java in src.zip should be a good
place to start. Enjoy.

Stan
George George - 17 Jun 2005 04:07 GMT
Thanks Stan,

>> Thanks Stan,
>>
[quoted text clipped - 13 lines]
>
>Stan

Your reply is just what I am looking for.

Have a nice weekend,
George
Robert Maas, see http://tinyurl.com/uh3t - 11 Jun 2005 05:01 GMT
> From: "George George via JavaKB.com" <forum@nospam.JavaKB.com>
> I want to clone the content of a Hashtable (its keys, its values and
[quoted text clipped - 3 lines]
> shallow copy of this hashtable. All the structure of the hashtable
> itself is copied, but the keys and values are not cloned. ...

There are only three "canonical" copy operations possible:
- Copying the reference (pointer) but don't copy any of the structure.
(Java does this by simple assignment of pointer variables)
- Copy the structure of the container itself, but just copy references
 to all components within the container.
(This is the shallow copy you are referring to.)
- Copy all the structure as deep as it goes. Unfortunately there can be
 pointer loops, so if you do this by simple recursive algorithm you
 get a recursive loop causing stack overflow. Java solves this in the
 serialization mechanism by building a hash table of all items copied
 and when it encounters a pointer to an item already in the table it
 makes a back-reference instead of copying it a second time.
(If this is the behaviour you want, why don't you just serialize to a
string then deserialize back to a new structure which is an isomorphic
copy of the original?)

If you want anything more than a shallow copy but less than a full deep
serialization, how do you expect Java to guess what you want??
You should write your own class which sub-classes Hashtable, and define
whatever kind of very-deep-but-not-all-the-way cloning you want.

By the way, for enlightenment, you really should read this:
  Linkname: P.S.: The Best of Intentions
       URL: http://www.nhplace.com/kent/PS/EQUAL.html
It's from the point of view of lisp, but it applies equally well to java.
George George - 12 Jun 2005 13:03 GMT
Thanks Robert,

>- Copy all the structure as deep as it goes. Unfortunately there can be
>  pointer loops, so if you do this by simple recursive algorithm you
[quoted text clipped - 5 lines]
> string then deserialize back to a new structure which is an isomorphic
> copy of the original?)

From your reply, I think you are a real expert in copy related field. :-) I
have a question from your reply. I do not quite understand how Java uses
serialization to make deep copy. Do you mean copy operation will invoke
serialization method internally in JVM?

It seems that Java uses a hash table and back-reference to solve the stack
overflow issue in traditional simple recursive algorithm (but I can not see
clearly how these methods could solve stack overflow issue, since in my
understanding of your reply, we still use hash table, back-reference
together with recursive algorithm, so recursive algorithm is still used and
stack overflow may still occur). I am very interested in this point. Could
you please explain it in more details or provide me some resources on this
topic?

regards,
George
Robert Maas, see http://tinyurl.com/uh3t - 26 Jun 2005 03:07 GMT
> From: "George George via JavaKB.com" <forum@JavaKB.com>
> I do not quite understand how Java uses serialization to make deep
> copy. Do you mean copy operation will invoke serialization method
> internally in JVM?

No. You get a serialization (first half of total copy) only when you
explicitly write data to a serialized-object stream.
 http://java.sun.com/j2se/1.3/docs/api/java/io/ObjectOutputStream.html
Then the second half of the totally-deep copy operation occurs when the
stream is used to reconstitute an object in a new location:
 http://java.sun.com/j2se/1.3/docs/api/java/io/ObjectInputStream.html

> It seems that Java uses a hash table and back-reference to solve the
> stack overflow issue in traditional simple recursive algorithm (but I
> can not see clearly how these methods could solve stack overflow issue,
> since in my understanding of your reply, we still use hash table,
> back-reference together with recursive algorithm, so recursive
> algorithm is still used and stack overflow may still occur).

The reason why stack overflow is *sure* to happen if you try to use a
naive recursive algorithm to copy a structure that contains a
pointer-loop is that you recurse deeper and deeper to keep encountering
that same loop over and over and over, never finding any bottom to the
structure so never returning from recursion. For example, imagine a
simple structure with two nodes, each of which points to the other:
 A <==> B
So you start at A, copy that, see pointer to B so you recurse into B to
copy that, and see pointer to A and recurse into that to copy A, and
see pointer to B but fail to notice you already followed that pointer
so you recurse into B again, etc. back and forth deeper and deeper
until the stack overflows. At some point you've copied:
 A -> B -> A1 -> B1 -> A2 -> B2 -> A3 -. B3 -> ...
many copies of each node and each direction of link, when stack
overflows.

If you keep a list of all nodes already visited, and never copy the
same node more than once, and never copy the same link more than once,
it works like this: Start at A, put A into table, see link to B, copy
link, see B is new node, put B into table, copy B, see link to A, copy
link, see A already in table, back off recursion to B, see no more
links from B, back off to A, see no more links from A, back out of top
level of recursion.

The only way such a table-keeping algorithm can get stack overflow is
if you really do have a very very very long chain of links, which
wouldn't happen in any reasonable program except if you make a linked
list to hold a very large list which is possibly unreasonable in the
first place. Instead of a very very very long linked list, it's
probably better to keep the data in a balanced binary tree of some
sort, so then a list of n elements requires only log(n) stack depth to
copy it all. For example, see:
 http://java.sun.com/j2se/1.3/docs/api/java/util/TreeSet.html
 http://java.sun.com/j2se/1.3/docs/api/java/util/TreeMap.html
George George - 29 Jun 2005 03:19 GMT
Thanks Robert,

>If you keep a list of all nodes already visited, and never copy the
>same node more than once, and never copy the same link more than once,
[quoted text clipped - 3 lines]
>links from B, back off to A, see no more links from A, back out of top
>level of recursion.

Your reply is very great! I am wondering where can I find some formal
tutorials or documents dealing with the copy algorithm? Are there any open
source algorithm implementations?

regards,
George


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.