30 December 2008

What do I need in JDK ?

I'll put some staff that I found that are much problem from time to time for me.

  • Lack of methods in File class...
  • String Comparator...
  • Thread Statics...
  • Add .shrink() for StringBuffer & StringBuilder...
  • 1st lvl type validation in standard Generics...
  • Generics variables...
  • Support for method to be able to return more than one variable...
  • Extended printStackTrace...
  • Read-Only Arrays...
  • 'forget' keyword...

Add to File class:

  • .copy(File)
  • .compareFileData(File)
  • . ...

String Comparator

String Comparator is horrible, it's provide much useless information. Who need 'this.charAt(k)-anotherString.charAt(k)' mixed with 'this.length()-anotherString.length()' ?
Let's see other way to implement comparator:
stringA.compare5StateTo(stringB)

  • return -2 if stringB is greater than stringA
  • return -1 if stringB start with stringA
  • return 0 if stringA equals stringB
  • return +1 if stringA start with stringB
  • return +2 if stringA is greater than stringB
Now time I need perform 3 operations to obtain same target.

Thread Statics

Static is global, but allow to make thread static would allow to remove 10~100% synchronization blocks. But it's really hard task and need to be deeply considered. Main problem is to prevent all thread-static data to be created with each thread, and make it available on demand only. Resources pool with auto–pinning to thread would be some solution as well.

Add .shrink() for StringBuffer & StringBuilder

Now time array inside of this Objects can only increase with it's size. This can be problem if happen that for one moment some one will put there a lot of data remove it and skip the object for new one.
Scenario:
We have 100 StringBuffer shared between threads (so we cannot dispose memory).
In 99,9..% of time StringBuffer store 1kb of data and in 0,001% there is 1mb of data.
In that case after some time there will be 100Mb unnecessarily allocated memory.
Other solution is conditional decreasing array size on .remove() (I prefer that).

1st lvl type validation in standard Generics

Personally I used to pass Class<? super ComponentType> in constructor. This solution can to be done easily. With no backward impact.
This cannot be overestimated as one of the best solution to prevent stupid bugs.
Second solution is to add validators on .add(...). More powder full but not as easy to use as previous one.

Generics variables

We have methods, classes, why there are no variables?

Support for method to be able to return more than one variable

Sample:

public static (int:index, double avg) some(...){
  if (isRequested(index)) index = binarySearch(...);
  if (isRequested(avg)){
    ...
  }
}

public static main(...){
  int index;
  index=some(...).index;
  double avg;
  (index=.index,avg=.avg)=some(...);

  some(...).{//here we have access to returned values here
    if (.avg>0){
      ...
    }
  };
}

Notice that isRequested() is a method which tells us if parameter needs to be returned.

Simple tuples are bad, the same as a return by reference because you need to remember parameters' sequence. That's why, even if we are able to return more than one value, we may have implemented the same method in a few different ways (and it's not so rare) depending on what we need.

You may do not see the power of this solution, however, when you analyze the given case you will see that the return values do not need to be counted if a used method is not requested for them.

Creating a new Class for that purpose is not a solution as well. If you analyze this you will see that it is not so rare to define unnecessary classes for each method ( or most of them) that do not allow us to tell if we need a full result or only part of it.

Have you ever wandered what you return when you add many elements to container? It really would be nice to get back:

Did even wander what would u return in case that when u add many elements to container. What would be nice to get back?

  • number of added elements
  • number of not added elements
  • list of added elements
  • list of not added elements
Of course, overkill might be a bad solution, as always.
I will describe it in more details on free time.

Extend printStackTrace

Allow to print stack trace only from throw exception point to exception handling point.

Read-Only Arrays

It's really hard to pinpoint what solution would be best.
At first I wander about 'context' access like:

Type[] readOnly =array.getReadOnly(from,to);
array[from] = t;
if (readOnly[0]==t) is always true

This would be peaty powder full solution, and it would allow to write more secure programs. Unfortunately every operation on arrays could bring unexpected problems if some one would use base array as buffer. Is that clear?
System.arraycopy(readOnly, srcPos, array, destPos, length);

We need check if readOnly and array point same space!

Other solution is about giving always read only arrays:
Type[] readOnly =array.copyAsReadOnly(from,to) array[from] = t;
if (readOnly[0]==t) can be false

'forget' keyword

with 'forget':

String data =readLine();
data = operate(data);
boolean isOk = data.contains(“contains”);
forget data;
// here we do not have access to data object

now time:
boolean isOk;
{
String data =readLine();
data = operate(data);
isOk = data.contains(“contains”);
}
// here we do not have access to data object

9 comments:

  1. @Support for method to be able to return more than one variable:

    It would be more general to introduce tuples instead of pure multiple return values. This is the way of Python and Erlang, Ruby uses arrays instead of tuples.

    You can introduce tuples using http://javatuple.com/, however it would be nice to have tuples as a part of the language and operate on them as easy as you do with arrays.

    ReplyDelete
  2. Thread-static is something like ThreadLocal ??? (JDK 5)

    ReplyDelete
  3. String Comparator and returning -2 -1 0 1 2:
    How often do you need it? In 1% of your work? It may make Comparator implementation much slower, and usually only -1 0 1 will be used. If you need it somewhere, implement this as your own subroutine.

    Thread Statics
    As kubek2k wrote - ThreadLocal is for this.

    Add .shrink() for StringBuffer & StringBuilder
    Adding .shrink() can be a bad idea - no programmer will remember about calling it.
    But automatic shrinking? Why not. AFAIK, even Java collections never shrink their internal storage. They should do this from time to time.
    Due to optimizations, this shouldn't happen at every element removal, but (for example), when there's very little memory.

    1st lvl type validation in standard Generics
    I don't understand it. :-)

    Generics variables
    What for? :-)

    Support for method to be able to return more than one variable
    C# has some support for this in form of out and inout parameter attributes. IMO, this is a bad idea - may quickly give methods with lots of arguments. This is what new types are for. Your code:
    int index;
    double avg;
    (index=.index,avg=.avg)=some(...);
    can be even simpler thanks to types:
    SomeResult someResult = some(...);
    And you use it:
    someResult.index, someResult.avg

    @skale
    I also disagree. Tuples built into language may have sense in languages like Prolog or ML (which have pattern recognition), but in in Java? Use arrays or new classes instead of tuples.

    Extend printStackTrace - make it shorter
    When I handle exception at some method, I may need to know who called this method. For example if somebody calls with a wrong parameter. I need to know who did it.
    So I think, the standard implementation of Exceptin.printStackTrace is right.
    Anyway, if you need your own printing method, you can implement it using Exception.getStackTrace().

    What did we loose with hiding object's address?
    Won't System.identityHashCode(x) or even x.hashCode() will be helpful for you? Hashcodes should be as different as possible. If 2 hashcodes have same values then, to be sure, just copare things using .equals(). This happens quite rarely, so perhaps won't destroy performance in O notation sense.
    If it really worsens performance, add a special 'address' field for each object, which will be incremented. If you can't add any fields to your objects, create Map<YourObjects, Integer> to store the addresses.
    Again, in 99.9% of cases you won't need it. Adding this extension for JDK would just make it messy with (almost) no use of it.

    In general. In 99.9% of cases we don't need any language or JDK extensions. Read also discussion at http://groups.google.com/group/lublin-jug/browse_thread/thread/4697e9eef8fd0453 (in Polish).

    ReplyDelete
  4. @ iirekm
    String Comparator and returning -2 -1 0 1 2:
    It is less than 1%, but it's impossible to implement it.
    Cos u need to copy array on each compare.

    ReplyDelete
  5. @kubek2k
    Thx for information.

    @iirekm
    Hashcodes do not solves all problems...

    >1st lvl type validation in standard Generics
    >I don't understand it. :-)
    It's like replace Object[] with ComponentType[] in ArrayList

    >Generics variables
    >What for? :-)
    You cannot create static generic class instance now.

    U have some good point at printStackTrace and I'll have to find better solution.

    ReplyDelete
  6. > @iirekm
    > Hashcodes do not solves all problems...
    If hashodes not, perhaps the map: object -> its "address". (but of course it won't be as fast as "pointers")

    If you really, really need to optimize, write it in C, or even Assembler, and include it to Java using JNI. (but this way you complicate builds of your program and make it less portable)

    >>Generics variables
    >>What for? :-)
    >You cannot create static generic class instance now.
    You mean something like: GenericType<YourType>.SOME_FUNNY_CONSTANT?

    Well, this is because Java GenericType<YourType> are in fact compiled to a single class: Generic type, and YourType is just replaced by Object (type erasure).
    You can't add many variables (for each of your types) in single GenericType class.

    As I wrote in LJUG, Java Generics although are useful, are also totally fucked up. The problem is more general: instead of type erasure, Java generics should be implemented in more C#- or C++-way. Each GenericType<YourType> should be a separate class.

    ReplyDelete
  7. >Each GenericType< YourType > should be a separate class.
    This is not good solution.
    Then would be: GenericType< YourType implements Comparable< YourType > >

    This solution is static. Problem is when u need to do some thing dynamically.
    I thing they start to go in correct way, but size of that task killed them for while. Note that dynamic generics ale same task as graph comparing/including task.

    >but this way you complicate builds of your program and make it less portable
    that why i wander if there is any way to determine some order in other way.
    What more hash is unstable in some algorithms, and can be changed if was implemented in that way.

    ReplyDelete
  8. >Add .shrink() for StringBuffer & StringBuilder

    You mean like .trimToSize()?

    ReplyDelete