Categories
discuss

What’s the current state of closures in Java?

Does anybody know, if closures will be in Java 7?

Answer

At Devoxx 2008, Mark Reinhold made it clear that closures will not be included in Java 7.


Wait! Closures will be included in Java 7. Mark Reinhold announced this reversal at Devoxx 2009.


Belay that! Closures (lambda expressions) have been deferred until Java 8. Follow Project Lambda (JSR 335) for more information.

Categories
discuss

java get file size efficiently

While googling, I see that using java.io.File#length() can be slow. FileChannel has a size() method that is available as well.

Is there an efficient way in java to get the file size?

Answer

Well, I tried to measure it up with the code below:

For runs = 1 and iterations = 1 the URL method is fastest most times followed by channel. I run this with some pause fresh about 10 times. So for one time access, using the URL is the fastest way I can think of:

LENGTH sum: 10626, per Iteration: 10626.0

CHANNEL sum: 5535, per Iteration: 5535.0

URL sum: 660, per Iteration: 660.0

For runs = 5 and iterations = 50 the picture draws different.

LENGTH sum: 39496, per Iteration: 157.984

CHANNEL sum: 74261, per Iteration: 297.044

URL sum: 95534, per Iteration: 382.136

File must be caching the calls to the filesystem, while channels and URL have some overhead.

Code:

import java.io.*;
import java.net.*;
import java.util.*;

public enum FileSizeBench {

    LENGTH {
        @Override
        public long getResult() throws Exception {
            File me = new File(FileSizeBench.class.getResource(
                    "FileSizeBench.class").getFile());
            return me.length();
        }
    },
    CHANNEL {
        @Override
        public long getResult() throws Exception {
            FileInputStream fis = null;
            try {
                File me = new File(FileSizeBench.class.getResource(
                        "FileSizeBench.class").getFile());
                fis = new FileInputStream(me);
                return fis.getChannel().size();
            } finally {
                fis.close();
            }
        }
    },
    URL {
        @Override
        public long getResult() throws Exception {
            InputStream stream = null;
            try {
                URL url = FileSizeBench.class
                        .getResource("FileSizeBench.class");
                stream = url.openStream();
                return stream.available();
            } finally {
                stream.close();
            }
        }
    };

    public abstract long getResult() throws Exception;

    public static void main(String[] args) throws Exception {
        int runs = 5;
        int iterations = 50;

        EnumMap<FileSizeBench, Long> durations = new EnumMap<FileSizeBench, Long>(FileSizeBench.class);

        for (int i = 0; i < runs; i++) {
            for (FileSizeBench test : values()) {
                if (!durations.containsKey(test)) {
                    durations.put(test, 0l);
                }
                long duration = testNow(test, iterations);
                durations.put(test, durations.get(test) + duration);
                // System.out.println(test + " took: " + duration + ", per iteration: " + ((double)duration / (double)iterations));
            }
        }

        for (Map.Entry<FileSizeBench, Long> entry : durations.entrySet()) {
            System.out.println();
            System.out.println(entry.getKey() + " sum: " + entry.getValue() + ", per Iteration: " + ((double)entry.getValue() / (double)(runs * iterations)));
        }

    }

    private static long testNow(FileSizeBench test, int iterations)
            throws Exception {
        long result = -1;
        long before = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            if (result == -1) {
                result = test.getResult();
                //System.out.println(result);
            } else if ((result = test.getResult()) != result) {
                 throw new Exception("variance detected!");
             }
        }
        return (System.nanoTime() - before) / 1000;
    }

}
Categories
discuss

How do you specify a port range for Java sockets?

In Java you can give the number zero as a single parameter for the Socket or DatagramSocket constructor. Java binds that Socket to a free port then. Is it possible to limit the port lookup to a specific range?

Answer

Hrm, after reading the docs, I don’t think you can. You can either bind to any port, then rebind if it is not acceptable, or repeatedly bind to a port in your range until you succeed. The second method is going to be most “efficient”.

I am uneasy about this answer, because it is… inelegant, yet I really can’t find anything else either :/

Categories
discuss

Refactoring Java factory method

There’s something very unsatisfactory about this code:

/*
Given a command string in which the first 8 characters are the command name
padded on the right with whitespace, construct the appropriate kind of 
Command object.
*/
public class CommandFactory {
     public Command getCommand(String cmd) {
         cmdName = cmd.subString(0,8).trim();

         if(cmdName.equals("START")) {
             return new StartCommand(cmd);
         }
         if(cmdName.equals("END")) {
             return new EndCommand(cmd);
         }
         // ... more commands in more if blocks here
         // else it's a bad command.
         return new InvalidCommand(cmd);
     }
}

I’m unrepentant about the multiple exit points – the structure is clear. But I’m not happy about the series of near-identical if statements. I’ve considered making a Map of Strings to Commands:

commandMap = new HashMap();
commandMap.put("START",StartCommand.class);
// ... etc.

… then using Reflection to make instances of the appropriate class looked up from the Map. However while conceptually elegant, this involves a fair amount of Reflection code that whoever inherits this code might not appreciate – although that cost might be offset by the benefits. All the lines hardcoding values into the commandMap smell almost as bad as the if block.

Even better would be if the factory’s constructor could scan the classpath for subclasses of Command, query them for String representations, and automatically add them them to its repertoire.

So – how should I go about refactoring this?

I guess some of the frameworks out there give me this kind of thing for free. Let’s assume I’m not in a position to migrate this stuff into such a framework.

Answer

Your map of strings to commands I think is good. You could even factor out the string command name to the constructor (i.e. shouldn’t StartCommand know that its command is “START”?) If you could do this, instantiation of your command objects is much simpler:

Class c = commandMap.get(cmdName);
if (c != null)
    return c.newInstance();
else
    throw new IllegalArgumentException(cmdName + " is not as valid command");

Another option is to create an enum of all your commands with links to the classes (assume all your command objects implement CommandInterface):

public enum Command
{
    START(StartCommand.class),
    END(EndCommand.class);

    private Class<? extends CommandInterface> mappedClass;
    private Command(Class<? extends CommandInterface> c) { mappedClass = c; }
    public CommandInterface getInstance()
    {
        return mappedClass.newInstance();
    }
}

since the toString of an enum is its name, you can use EnumSet to locate the right object and get the class from within.

Categories
discuss

How do you implement position-sensitive zooming inside a JScrollPane?

I am trying to implement position-sensitive zooming inside a JScrollPane. The JScrollPane contains a component with a customized paint that will draw itself inside whatever space it is allocated – so zooming is as easy as using a MouseWheelListener that resizes the inner component as required.

But I also want zooming into (or out of) a point to keep that point as central as possible within the resulting zoomed-in (or -out) view (this is what I refer to as ‘position-sensitive’ zooming), similar to how zooming works in google maps. I am sure this has been done many times before – does anybody know the “right” way to do it under Java Swing?. Would it be better to play with Graphic2D‘s transformations instead of using JScrollPanes?

Sample code follows:

package test;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

public class FPanel extends javax.swing.JPanel {

private Dimension preferredSize = new Dimension(400, 400);    
private Rectangle2D[] rects = new Rectangle2D[50];

public static void main(String[] args) {        
    JFrame jf = new JFrame("test");
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.setSize(400, 400);
    jf.add(new JScrollPane(new FPanel()));
    jf.setVisible(true);
}    

public FPanel() {
    // generate rectangles with pseudo-random coords
    for (int i=0; i<rects.length; i++) {
        rects[i] = new Rectangle2D.Double(
                Math.random()*.8, Math.random()*.8, 
                Math.random()*.2, Math.random()*.2);
    }
    // mouse listener to detect scrollwheel events
    addMouseWheelListener(new MouseWheelListener() {
        public void mouseWheelMoved(MouseWheelEvent e) {
            updatePreferredSize(e.getWheelRotation(), e.getPoint());
        }
    });
}

private void updatePreferredSize(int n, Point p) {
    double d = (double) n * 1.08;
    d = (n > 0) ? 1 / d : -d;
    int w = (int) (getWidth() * d);
    int h = (int) (getHeight() * d);
    preferredSize.setSize(w, h);
    getParent().doLayout();
    // Question: how do I keep 'p' centered in the resulting view?
}

public Dimension getPreferredSize() {
    return preferredSize;
}

private Rectangle2D r = new Rectangle2D.Float();
public void paint(Graphics g) {
    super.paint(g);
    g.setColor(Color.red);
    int w = getWidth();
    int h = getHeight();
    for (Rectangle2D rect : rects) {
        r.setRect(rect.getX() * w, rect.getY() * h, 
                rect.getWidth() * w, rect.getHeight() * h);
        ((Graphics2D)g).draw(r);
    }       
  }
}

Answer

Tested this, seems to work…

private void updatePreferredSize(int n, Point p) {
    double d = (double) n * 1.08;
    d = (n > 0) ? 1 / d : -d;

    int w = (int) (getWidth() * d);
    int h = (int) (getHeight() * d);
    preferredSize.setSize(w, h);

    int offX = (int)(p.x * d) - p.x;
    int offY = (int)(p.y * d) - p.y;
    setLocation(getLocation().x-offX,getLocation().y-offY);

    getParent().doLayout();
}

Update

Here is an explanation: the point p is the location of the mouse relative to the FPanel. Since you are scaling the size of the panel, the location of p (relative to the size of the panel) will scale by the same factor. By subtracting the current location from the scaled location, you get how much the point ‘shifts’ when the panel is resized. Then it is simply a matter of shifting the panel location in the scroll pane by the same amount in the opposite direction to put p back under the mouse cursor.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..