Index: trunk/src/org/openstreetmap/josm/data/APIDataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/APIDataSet.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/APIDataSet.java	(revision 10608)
@@ -5,5 +5,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -335,10 +334,5 @@
             Collections.sort(
                     ret,
-                    new Comparator<Relation>() {
-                        @Override
-                        public int compare(Relation o1, Relation o2) {
-                            return Integer.compare(uploadOrder.indexOf(o1), uploadOrder.indexOf(o2));
-                        }
-                    }
+                    (o1, o2) -> Integer.compare(uploadOrder.indexOf(o1), uploadOrder.indexOf(o2))
                     );
             return ret;
Index: trunk/src/org/openstreetmap/josm/data/AutosaveTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/AutosaveTask.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/AutosaveTask.java	(revision 10608)
@@ -243,12 +243,8 @@
 
     protected void displayNotification() {
-        GuiHelper.runInEDT(new Runnable() {
-            @Override
-            public void run() {
+        GuiHelper.runInEDT(
                 new Notification(tr("Your work has been saved automatically."))
                 .setDuration(Notification.TIME_SHORT)
-                .show();
-            }
-        });
+                ::show);
     }
 
@@ -346,10 +342,5 @@
         File jvmDir = new File(System.getProperty("java.io.tmpdir") + File.separator + "hsperfdata_" + System.getProperty("user.name"));
         if (jvmDir.exists() && jvmDir.canRead()) {
-            File[] files = jvmDir.listFiles(new FileFilter() {
-                @Override
-                public boolean accept(File file) {
-                    return file.getName().equals(jvmId) && file.isFile();
-                }
-            });
+            File[] files = jvmDir.listFiles((FileFilter) file -> file.getName().equals(jvmId) && file.isFile());
             return files != null && files.length == 1;
         }
@@ -365,16 +356,13 @@
         final OpenFileTask openFileTsk = new OpenFileTask(files, null, tr("Restoring files"));
         final Future<?> openFilesFuture = Main.worker.submit(openFileTsk);
-        return Main.worker.submit(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    // Wait for opened tasks to be generated.
-                    openFilesFuture.get();
-                    for (File f: openFileTsk.getSuccessfullyOpenedFiles()) {
-                        moveToDeletedLayersFolder(f);
-                    }
-                } catch (InterruptedException | ExecutionException e) {
-                    Main.error(e);
-                }
+        return Main.worker.submit(() -> {
+            try {
+                // Wait for opened tasks to be generated.
+                openFilesFuture.get();
+                for (File f: openFileTsk.getSuccessfullyOpenedFiles()) {
+                    moveToDeletedLayersFolder(f);
+                }
+            } catch (InterruptedException | ExecutionException e) {
+                Main.error(e);
             }
         });
Index: trunk/src/org/openstreetmap/josm/data/CustomConfigurator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/CustomConfigurator.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/CustomConfigurator.java	(revision 10608)
@@ -372,50 +372,44 @@
 
         final ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask();
-        Runnable r = new Runnable() {
-            @Override
-            public void run() {
-                if (task.isCanceled()) return;
-                synchronized (CustomConfigurator.class) {
-                    try { // proceed only after all other tasks were finished
-                        while (busy) CustomConfigurator.class.wait();
-                    } catch (InterruptedException ex) {
-                        Main.warn("InterruptedException while reading local plugin information");
-                    }
-
-                    SwingUtilities.invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            List<PluginInformation> availablePlugins = task.getAvailablePlugins();
-                            List<PluginInformation> toInstallPlugins = new ArrayList<>();
-                            List<PluginInformation> toRemovePlugins = new ArrayList<>();
-                            List<PluginInformation> toDeletePlugins = new ArrayList<>();
-                            for (PluginInformation pi: availablePlugins) {
-                                String name = pi.name.toLowerCase(Locale.ENGLISH);
-                                if (installList.contains(name)) toInstallPlugins.add(pi);
-                                if (removeList.contains(name)) toRemovePlugins.add(pi);
-                                if (deleteList.contains(name)) toDeletePlugins.add(pi);
-                            }
-                            if (!installList.isEmpty()) {
-                                PluginDownloadTask pluginDownloadTask =
-                                        new PluginDownloadTask(Main.parent, toInstallPlugins, tr("Installing plugins"));
-                                Main.worker.submit(pluginDownloadTask);
-                            }
-                            Collection<String> pls = new ArrayList<>(Main.pref.getCollection("plugins"));
-                            for (PluginInformation pi: toInstallPlugins) {
-                                if (!pls.contains(pi.name)) {
-                                    pls.add(pi.name);
-                                }
-                            }
-                            for (PluginInformation pi: toRemovePlugins) {
-                                pls.remove(pi.name);
-                            }
-                            for (PluginInformation pi: toDeletePlugins) {
-                                pls.remove(pi.name);
-                                new File(Main.pref.getPluginsDirectory(), pi.name+".jar").deleteOnExit();
-                            }
-                            Main.pref.putCollection("plugins", pls);
+        Runnable r = () -> {
+            if (task.isCanceled()) return;
+            synchronized (CustomConfigurator.class) {
+                try { // proceed only after all other tasks were finished
+                    while (busy) CustomConfigurator.class.wait();
+                } catch (InterruptedException ex) {
+                    Main.warn(ex, "InterruptedException while reading local plugin information");
+                }
+
+                SwingUtilities.invokeLater(() -> {
+                    List<PluginInformation> availablePlugins = task.getAvailablePlugins();
+                    List<PluginInformation> toInstallPlugins = new ArrayList<>();
+                    List<PluginInformation> toRemovePlugins = new ArrayList<>();
+                    List<PluginInformation> toDeletePlugins = new ArrayList<>();
+                    for (PluginInformation pi1: availablePlugins) {
+                        String name = pi1.name.toLowerCase(Locale.ENGLISH);
+                        if (installList.contains(name)) toInstallPlugins.add(pi1);
+                        if (removeList.contains(name)) toRemovePlugins.add(pi1);
+                        if (deleteList.contains(name)) toDeletePlugins.add(pi1);
+                    }
+                    if (!installList.isEmpty()) {
+                        PluginDownloadTask pluginDownloadTask =
+                                new PluginDownloadTask(Main.parent, toInstallPlugins, tr("Installing plugins"));
+                        Main.worker.submit(pluginDownloadTask);
+                    }
+                    Collection<String> pls = new ArrayList<>(Main.pref.getCollection("plugins"));
+                    for (PluginInformation pi2: toInstallPlugins) {
+                        if (!pls.contains(pi2.name)) {
+                            pls.add(pi2.name);
                         }
-                    });
-                }
+                    }
+                    for (PluginInformation pi3: toRemovePlugins) {
+                        pls.remove(pi3.name);
+                    }
+                    for (PluginInformation pi4: toDeletePlugins) {
+                        pls.remove(pi4.name);
+                        new File(Main.pref.getPluginsDirectory(), pi4.name+".jar").deleteOnExit();
+                    }
+                    Main.pref.putCollection("plugins", pls);
+                });
             }
         };
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 10608)
@@ -138,10 +138,6 @@
     protected final SortedMap<String, Setting<?>> defaultsMap = new TreeMap<>();
 
-    private final Predicate<Entry<String, Setting<?>>> NO_DEFAULT_SETTINGS_ENTRY = new Predicate<Entry<String, Setting<?>>>() {
-        @Override
-        public boolean evaluate(Entry<String, Setting<?>> e) {
-            return !e.getValue().equals(defaultsMap.get(e.getKey()));
-        }
-    };
+    private final Predicate<Entry<String, Setting<?>>> NO_DEFAULT_SETTINGS_ENTRY =
+            e -> !e.getValue().equals(defaultsMap.get(e.getKey()));
 
     /**
Index: trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java	(revision 10608)
@@ -125,10 +125,5 @@
             if (limit != null) {
                 limit.acquire();
-                jcsJob.setFinishedTask(new Runnable() {
-                    @Override
-                    public void run() {
-                        releaseSemaphore(jcsJob);
-                    }
-                });
+                jcsJob.setFinishedTask(() -> releaseSemaphore(jcsJob));
             }
         }
@@ -141,10 +136,5 @@
             ret = limit.tryAcquire();
             if (ret) {
-                job.setFinishedTask(new Runnable() {
-                    @Override
-                    public void run() {
-                        releaseSemaphore(job);
-                    }
-                });
+                job.setFinishedTask(() -> releaseSemaphore(job));
             }
         }
Index: trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 10608)
@@ -362,10 +362,5 @@
      */
     public Iterable<Collection<WayPoint>> getLinesIterable(final boolean[] trackVisibility) {
-        return new Iterable<Collection<WayPoint>>() {
-            @Override
-            public Iterator<Collection<WayPoint>> iterator() {
-                return new LinesIterator(GpxData.this, trackVisibility);
-            }
-        };
+        return () -> new LinesIterator(GpxData.this, trackVisibility);
     }
 
Index: trunk/src/org/openstreetmap/josm/data/imagery/CachedAttributionBingAerialTileSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/CachedAttributionBingAerialTileSource.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/imagery/CachedAttributionBingAerialTileSource.java	(revision 10608)
@@ -61,24 +61,20 @@
     @Override
     protected Callable<List<Attribution>> getAttributionLoaderCallable() {
-        return new Callable<List<Attribution>>() {
-
-            @Override
-            public List<Attribution> call() throws Exception {
-                BingAttributionData attributionLoader = new BingAttributionData();
-                int waitTimeSec = 1;
-                while (true) {
-                    try {
-                        String xml = attributionLoader.updateIfRequiredString();
-                        List<Attribution> ret = parseAttributionText(new InputSource(new StringReader(xml)));
-                        if (attributionDownloadedTask != null) {
-                            GuiHelper.runInEDT(attributionDownloadedTask);
-                            attributionDownloadedTask = null;
-                        }
-                        return ret;
-                    } catch (IOException ex) {
-                        Main.warn(ex, "Could not connect to Bing API. Will retry in " + waitTimeSec + " seconds.");
-                        Thread.sleep(waitTimeSec * 1000L);
-                        waitTimeSec *= 2;
+        return () -> {
+            BingAttributionData attributionLoader = new BingAttributionData();
+            int waitTimeSec = 1;
+            while (true) {
+                try {
+                    String xml = attributionLoader.updateIfRequiredString();
+                    List<Attribution> ret = parseAttributionText(new InputSource(new StringReader(xml)));
+                    if (attributionDownloadedTask != null) {
+                        GuiHelper.runInEDT(attributionDownloadedTask);
+                        attributionDownloadedTask = null;
                     }
+                    return ret;
+                } catch (IOException ex) {
+                    Main.warn(ex, "Could not connect to Bing API. Will retry in " + waitTimeSec + " seconds.");
+                    Thread.sleep(waitTimeSec * 1000L);
+                    waitTimeSec *= 2;
                 }
             }
Index: trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java	(revision 10608)
@@ -14,5 +14,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
@@ -85,11 +84,6 @@
 
     private static class TileMatrixSetBuilder {
-        SortedSet<TileMatrix> tileMatrix = new TreeSet<>(new Comparator<TileMatrix>() {
-            @Override
-            public int compare(TileMatrix o1, TileMatrix o2) {
-                // reverse the order, so it will be from greatest (lowest zoom level) to lowest value (highest zoom level)
-                return -1 * Double.compare(o1.scaleDenominator, o2.scaleDenominator);
-            }
-        }); // sorted by zoom level
+        // sorted by zoom level
+        SortedSet<TileMatrix> tileMatrix = new TreeSet<>((o1, o2) -> -1 * Double.compare(o1.scaleDenominator, o2.scaleDenominator));
         private String crs;
         private String identifier;
Index: trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java	(revision 10608)
@@ -16,5 +16,4 @@
 import org.openstreetmap.josm.gui.JosmUserIdentityManager;
 import org.openstreetmap.josm.gui.util.GuiHelper;
-import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -70,9 +69,7 @@
 
     protected void fireChangesetCacheEvent(final ChangesetCacheEvent e) {
-        GuiHelper.runInEDT(new Runnable() {
-            @Override public void run() {
-                for (ChangesetCacheListener l: listeners) {
-                    l.changesetCacheUpdated(e);
-                }
+        GuiHelper.runInEDT(() -> {
+            for (ChangesetCacheListener l: listeners) {
+                l.changesetCacheUpdated(e);
             }
         });
@@ -206,10 +203,6 @@
             return getOpenChangesets();
         } else {
-            return new ArrayList<>(Utils.filter(getOpenChangesets(), new Predicate<Changeset>() {
-                @Override
-                public boolean evaluate(Changeset object) {
-                    return JosmUserIdentityManager.getInstance().isCurrentUser(object.getUser());
-                }
-            }));
+            return new ArrayList<>(Utils.filter(getOpenChangesets(),
+                    object -> JosmUserIdentityManager.getInstance().isCurrentUser(object.getUser())));
         }
     }
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 10608)
@@ -47,5 +47,4 @@
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
 import org.openstreetmap.josm.tools.FilteredCollection;
-import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Predicates;
 import org.openstreetmap.josm.tools.SubclassFilteredCollection;
@@ -614,10 +613,5 @@
      */
     public Collection<OsmPrimitive> getSelectedNodesAndWays() {
-        return new FilteredCollection<>(getSelected(), new Predicate<OsmPrimitive>() {
-            @Override
-            public boolean evaluate(OsmPrimitive primitive) {
-                return primitive instanceof Node || primitive instanceof Way;
-            }
-        });
+        return new FilteredCollection<>(getSelected(), primitive -> primitive instanceof Node || primitive instanceof Way);
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/NoteData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/NoteData.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/osm/NoteData.java	(revision 10608)
@@ -16,5 +16,4 @@
 import org.openstreetmap.josm.data.notes.NoteComment;
 import org.openstreetmap.josm.gui.JosmUserIdentityManager;
-import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -37,52 +36,38 @@
      * Within each subgroup it sorts by ID
      */
-    public static final Comparator<Note> DEFAULT_COMPARATOR = new Comparator<Note>() {
-        @Override
-        public int compare(Note n1, Note n2) {
-            if (n1.getId() < 0 && n2.getId() > 0) {
-                return 1;
-            }
-            if (n1.getId() > 0 && n2.getId() < 0) {
-                return -1;
-            }
-            if (n1.getState() == State.CLOSED && n2.getState() == State.OPEN) {
-                return 1;
-            }
-            if (n1.getState() == State.OPEN && n2.getState() == State.CLOSED) {
-                return -1;
-            }
-            return Long.compare(Math.abs(n1.getId()), Math.abs(n2.getId()));
-        }
+    public static final Comparator<Note> DEFAULT_COMPARATOR = (n1, n2) -> {
+        if (n1.getId() < 0 && n2.getId() > 0) {
+            return 1;
+        }
+        if (n1.getId() > 0 && n2.getId() < 0) {
+            return -1;
+        }
+        if (n1.getState() == State.CLOSED && n2.getState() == State.OPEN) {
+            return 1;
+        }
+        if (n1.getState() == State.OPEN && n2.getState() == State.CLOSED) {
+            return -1;
+        }
+        return Long.compare(Math.abs(n1.getId()), Math.abs(n2.getId()));
     };
 
     /** Sorts notes strictly by creation date */
-    public static final Comparator<Note> DATE_COMPARATOR = new Comparator<Note>() {
-        @Override
-        public int compare(Note n1, Note n2) {
+    public static final Comparator<Note> DATE_COMPARATOR = (n1, n2) -> n1.getCreatedAt().compareTo(n2.getCreatedAt());
+
+    /** Sorts notes by user, then creation date */
+    public static final Comparator<Note> USER_COMPARATOR = (n1, n2) -> {
+        String n1User = n1.getFirstComment().getUser().getName();
+        String n2User = n2.getFirstComment().getUser().getName();
+        if (n1User.equals(n2User)) {
             return n1.getCreatedAt().compareTo(n2.getCreatedAt());
         }
+        return n1.getFirstComment().getUser().getName().compareTo(n2.getFirstComment().getUser().getName());
     };
 
-    /** Sorts notes by user, then creation date */
-    public static final Comparator<Note> USER_COMPARATOR = new Comparator<Note>() {
-        @Override
-        public int compare(Note n1, Note n2) {
-            String n1User = n1.getFirstComment().getUser().getName();
-            String n2User = n2.getFirstComment().getUser().getName();
-            if (n1User.equals(n2User)) {
-                return n1.getCreatedAt().compareTo(n2.getCreatedAt());
-            }
-            return n1.getFirstComment().getUser().getName().compareTo(n2.getFirstComment().getUser().getName());
-        }
-    };
-
     /** Sorts notes by the last modified date */
-    public static final Comparator<Note> LAST_ACTION_COMPARATOR = new Comparator<Note>() {
-        @Override
-        public int compare(Note n1, Note n2) {
-            Date n1Date = n1.getComments().get(n1.getComments().size()-1).getCommentTimestamp();
-            Date n2Date = n2.getComments().get(n2.getComments().size()-1).getCommentTimestamp();
-            return n1Date.compareTo(n2Date);
-        }
+    public static final Comparator<Note> LAST_ACTION_COMPARATOR = (n1, n2) -> {
+        Date n1Date = n1.getComments().get(n1.getComments().size()-1).getCommentTimestamp();
+        Date n2Date = n2.getComments().get(n2.getComments().size()-1).getCommentTimestamp();
+        return n1Date.compareTo(n2Date);
     };
 
@@ -169,10 +154,5 @@
             } else {
                 final Note existingNote = noteList.get(newNote);
-                final boolean isDirty = Utils.exists(existingNote.getComments(), new Predicate<NoteComment>() {
-                    @Override
-                    public boolean evaluate(NoteComment object) {
-                        return object.isNew();
-                    }
-                });
+                final boolean isDirty = Utils.exists(existingNote.getComments(), object -> object.isNew());
                 if (!isDirty) {
                     noteList.put(newNote);
Index: trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 10608)
@@ -110,4 +110,31 @@
 
     /**
+     * A tagged way that matches this pattern has a direction.
+     * @see #FLAG_HAS_DIRECTIONS
+     */
+    private static volatile Match directionKeys;
+
+    /**
+     * A tagged way that matches this pattern has a direction that is reversed.
+     * <p>
+     * This pattern should be a subset of {@link #directionKeys}
+     * @see #FLAG_DIRECTION_REVERSED
+     */
+    private static volatile Match reversedDirectionKeys;
+
+    static {
+        String reversedDirectionDefault = "oneway=\"-1\"";
+
+        String directionDefault = "oneway? | (aerialway=* -aerialway=station) | "+
+                "waterway=stream | waterway=river | waterway=ditch | waterway=drain | "+
+                "\"piste:type\"=downhill | \"piste:type\"=sled | man_made=\"piste:halfpipe\" | "+
+                "junction=roundabout | (highway=motorway & -oneway=no & -oneway=reversible) | "+
+                "(highway=motorway_link & -oneway=no & -oneway=reversible)";
+
+        reversedDirectionKeys = compileDirectionKeys("tags.reversed_direction", reversedDirectionDefault);
+        directionKeys = compileDirectionKeys("tags.direction", directionDefault);
+    }
+
+    /**
      * Replies the sub-collection of {@link OsmPrimitive}s of type <code>type</code> present in
      * another collection of {@link OsmPrimitive}s. The result collection is a list.
@@ -174,56 +201,32 @@
      * @see OsmPrimitive#isUsable()
      */
-    public static final Predicate<OsmPrimitive> isUsablePredicate = new Predicate<OsmPrimitive>() {
-        @Override
-        public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.isUsable();
-        }
-    };
+    public static final Predicate<OsmPrimitive> isUsablePredicate = primitive -> primitive.isUsable();
 
     /**
      * A predicate filtering primitives that are selectable.
      */
-    public static final Predicate<OsmPrimitive> isSelectablePredicate = new Predicate<OsmPrimitive>() {
-        @Override
-        public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.isSelectable();
-        }
-    };
+    public static final Predicate<OsmPrimitive> isSelectablePredicate = primitive -> primitive.isSelectable();
 
     /**
      * A predicate filtering primitives that are not deleted.
      */
-    public static final Predicate<OsmPrimitive> nonDeletedPredicate = new Predicate<OsmPrimitive>() {
-        @Override public boolean evaluate(OsmPrimitive primitive) {
-            return !primitive.isDeleted();
-        }
-    };
+    public static final Predicate<OsmPrimitive> nonDeletedPredicate = primitive -> !primitive.isDeleted();
 
     /**
      * A predicate filtering primitives that are not deleted and not incomplete.
      */
-    public static final Predicate<OsmPrimitive> nonDeletedCompletePredicate = new Predicate<OsmPrimitive>() {
-        @Override public boolean evaluate(OsmPrimitive primitive) {
-            return !primitive.isDeleted() && !primitive.isIncomplete();
-        }
-    };
+    public static final Predicate<OsmPrimitive> nonDeletedCompletePredicate =
+            primitive -> !primitive.isDeleted() && !primitive.isIncomplete();
 
     /**
      * A predicate filtering primitives that are not deleted and not incomplete and that are not a relation.
      */
-    public static final Predicate<OsmPrimitive> nonDeletedPhysicalPredicate = new Predicate<OsmPrimitive>() {
-        @Override public boolean evaluate(OsmPrimitive primitive) {
-            return !primitive.isDeleted() && !primitive.isIncomplete() && !(primitive instanceof Relation);
-        }
-    };
+    public static final Predicate<OsmPrimitive> nonDeletedPhysicalPredicate =
+            primitive -> !primitive.isDeleted() && !primitive.isIncomplete() && !(primitive instanceof Relation);
 
     /**
      * A predicate filtering primitives that are modified
      */
-    public static final Predicate<OsmPrimitive> modifiedPredicate = new Predicate<OsmPrimitive>() {
-        @Override public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.isModified();
-        }
-    };
+    public static final Predicate<OsmPrimitive> modifiedPredicate = primitive -> primitive.isModified();
 
     /**
@@ -245,9 +248,6 @@
      * A predicate filtering multipolygon relations.
      */
-    public static final Predicate<OsmPrimitive> multipolygonPredicate = new Predicate<OsmPrimitive>() {
-        @Override public boolean evaluate(OsmPrimitive primitive) {
-            return primitive.getClass() == Relation.class && ((Relation) primitive).isMultipolygon();
-        }
-    };
+    public static final Predicate<OsmPrimitive> multipolygonPredicate =
+            primitive -> primitive.getClass() == Relation.class && ((Relation) primitive).isMultipolygon();
 
     /**
@@ -256,10 +256,5 @@
      * @see #FLAG_HAS_DIRECTIONS
      */
-    public static final Predicate<Tag> directionalKeyPredicate = new Predicate<Tag>() {
-        @Override
-        public boolean evaluate(Tag tag) {
-            return directionKeys.match(tag);
-        }
-    };
+    public static final Predicate<Tag> directionalKeyPredicate = tag -> directionKeys.match(tag);
 
     /**
@@ -843,31 +838,4 @@
     }
 
-    /**
-     * A tagged way that matches this pattern has a direction.
-     * @see #FLAG_HAS_DIRECTIONS
-     */
-    private static volatile Match directionKeys;
-
-    /**
-     * A tagged way that matches this pattern has a direction that is reversed.
-     * <p>
-     * This pattern should be a subset of {@link #directionKeys}
-     * @see #FLAG_DIRECTION_REVERSED
-     */
-    private static volatile Match reversedDirectionKeys;
-
-    static {
-        String reversedDirectionDefault = "oneway=\"-1\"";
-
-        String directionDefault = "oneway? | (aerialway=* -aerialway=station) | "+
-                "waterway=stream | waterway=river | waterway=ditch | waterway=drain | "+
-                "\"piste:type\"=downhill | \"piste:type\"=sled | man_made=\"piste:halfpipe\" | "+
-                "junction=roundabout | (highway=motorway & -oneway=no & -oneway=reversible) | "+
-                "(highway=motorway_link & -oneway=no & -oneway=reversible)";
-
-        reversedDirectionKeys = compileDirectionKeys("tags.reversed_direction", reversedDirectionDefault);
-        directionKeys = compileDirectionKeys("tags.direction", directionDefault);
-    }
-
     private static Match compileDirectionKeys(String prefName, String defaultValue) throws AssertionError {
         try {
Index: trunk/src/org/openstreetmap/josm/data/osm/Relation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/osm/Relation.java	(revision 10608)
@@ -15,6 +15,6 @@
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.tools.CopyList;
-import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
+import org.openstreetmap.josm.tools.Utils.Function;
 
 /**
@@ -349,10 +349,5 @@
      */
     public Collection<RelationMember> getMembersFor(final Collection<? extends OsmPrimitive> primitives) {
-        return Utils.filter(getMembers(), new Predicate<RelationMember>() {
-            @Override
-            public boolean evaluate(RelationMember member) {
-                return primitives.contains(member.getMember());
-            }
-        });
+        return Utils.filter(getMembers(), member -> primitives.contains(member.getMember()));
     }
 
@@ -405,10 +400,5 @@
 
     public List<OsmPrimitive> getMemberPrimitivesList() {
-        return Utils.transform(getMembers(), new Utils.Function<RelationMember, OsmPrimitive>() {
-            @Override
-            public OsmPrimitive apply(RelationMember x) {
-                return x.getMember();
-            }
-        });
+        return Utils.transform(getMembers(), (Function<RelationMember, OsmPrimitive>) x -> x.getMember());
     }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/event/SelectionEventManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/event/SelectionEventManager.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/osm/event/SelectionEventManager.java	(revision 10608)
@@ -88,10 +88,7 @@
     }
 
-    private final Runnable edtRunnable = new Runnable() {
-        @Override
-        public void run() {
-            if (selection != null) {
-                fireEvents(inEDTListeners, selection);
-            }
+    private final Runnable edtRunnable = () -> {
+        if (selection != null) {
+            fireEvents(inEDTListeners, selection);
         }
     };
Index: trunk/src/org/openstreetmap/josm/data/osm/history/History.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/history/History.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/osm/history/History.java	(revision 10608)
@@ -5,5 +5,4 @@
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
@@ -70,13 +69,5 @@
     public History sortAscending() {
         List<HistoryOsmPrimitive> copy = new ArrayList<>(versions);
-        Collections.sort(
-                copy,
-                new Comparator<HistoryOsmPrimitive>() {
-                    @Override
-                    public int compare(HistoryOsmPrimitive o1, HistoryOsmPrimitive o2) {
-                        return o1.compareTo(o2);
-                    }
-                }
-            );
+        Collections.sort(copy, (o1, o2) -> o1.compareTo(o2));
         return new History(id, type, copy);
     }
@@ -88,13 +79,5 @@
     public History sortDescending() {
         List<HistoryOsmPrimitive> copy = new ArrayList<>(versions);
-        Collections.sort(
-                copy,
-                new Comparator<HistoryOsmPrimitive>() {
-                    @Override
-                    public int compare(HistoryOsmPrimitive o1, HistoryOsmPrimitive o2) {
-                        return o2.compareTo(o1);
-                    }
-                }
-            );
+        Collections.sort(copy, (o1, o2) -> o2.compareTo(o1));
         return new History(id, type, copy);
     }
@@ -106,13 +89,5 @@
      */
     public History from(final Date fromDate) {
-        return filter(
-                this,
-                new FilterPredicate() {
-                    @Override
-                    public boolean matches(HistoryOsmPrimitive primitive) {
-                        return primitive.getTimestamp().compareTo(fromDate) >= 0;
-                    }
-                }
-            );
+        return filter(this, primitive -> primitive.getTimestamp().compareTo(fromDate) >= 0);
     }
 
@@ -123,13 +98,5 @@
      */
     public History until(final Date untilDate) {
-        return filter(
-                this,
-                new FilterPredicate() {
-                    @Override
-                    public boolean matches(HistoryOsmPrimitive primitive) {
-                        return primitive.getTimestamp().compareTo(untilDate) <= 0;
-                    }
-                }
-            );
+        return filter(this, primitive -> primitive.getTimestamp().compareTo(untilDate) <= 0);
     }
 
@@ -150,13 +117,5 @@
      */
     public History from(final long fromVersion) {
-        return filter(
-                this,
-                new FilterPredicate() {
-                    @Override
-                    public boolean matches(HistoryOsmPrimitive primitive) {
-                        return primitive.getVersion() >= fromVersion;
-                    }
-                }
-            );
+        return filter(this, primitive -> primitive.getVersion() >= fromVersion);
     }
 
@@ -167,13 +126,5 @@
      */
     public History until(final long untilVersion) {
-        return filter(
-                this,
-                new FilterPredicate() {
-                    @Override
-                    public boolean matches(HistoryOsmPrimitive primitive) {
-                        return primitive.getVersion() <= untilVersion;
-                    }
-                }
-            );
+        return filter(this, primitive -> primitive.getVersion() <= untilVersion);
     }
 
@@ -194,13 +145,5 @@
      */
     public History forUserId(final long uid) {
-        return filter(
-                this,
-                new FilterPredicate() {
-                    @Override
-                    public boolean matches(HistoryOsmPrimitive primitive) {
-                        return primitive.getUser() != null && primitive.getUser().getId() == uid;
-                    }
-                }
-            );
+        return filter(this, primitive -> primitive.getUser() != null && primitive.getUser().getId() == uid);
     }
 
@@ -283,5 +226,5 @@
      * @throws IndexOutOfBoundsException if index out or range
      */
-    public HistoryOsmPrimitive get(int idx) throws IndexOutOfBoundsException {
+    public HistoryOsmPrimitive get(int idx) {
         if (idx < 0 || idx >= versions.size())
             throw new IndexOutOfBoundsException(MessageFormat.format(
@@ -338,5 +281,5 @@
     public String toString() {
         StringBuilder result = new StringBuilder("History ["
-                + (type != null ? "type=" + type + ", " : "") + "id=" + id);
+                + (type != null ? ("type=" + type + ", ") : "") + "id=" + id);
         if (versions != null) {
             result.append(", versions=\n");
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/Addresses.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/Addresses.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/Addresses.java	(revision 10608)
@@ -29,5 +29,4 @@
 import org.openstreetmap.josm.tools.Geometry;
 import org.openstreetmap.josm.tools.Pair;
-import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -92,15 +91,10 @@
             // warning level only if several relations have different names, see #10945
             final String name = list.get(0).get("name");
-            if (name == null || Utils.filter(list, new Predicate<Relation>() {
-                @Override
-                public boolean evaluate(Relation r) {
-                    return name.equals(r.get("name"));
-                }
-            }).size() < list.size()) {
+            if (name == null || Utils.filter(list, r -> name.equals(r.get("name"))).size() < list.size()) {
                 level = Severity.WARNING;
             } else {
                 level = Severity.OTHER;
             }
-            List<OsmPrimitive> errorList = new ArrayList<OsmPrimitive>(list);
+            List<OsmPrimitive> errorList = new ArrayList<>(list);
             errorList.add(0, p);
             errors.add(new AddressError(this, MULTIPLE_STREET_RELATIONS, level, errorList,
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/Highways.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/Highways.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/Highways.java	(revision 10608)
@@ -24,5 +24,4 @@
 import org.openstreetmap.josm.data.validation.Test;
 import org.openstreetmap.josm.data.validation.TestError;
-import org.openstreetmap.josm.tools.Predicate;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -175,10 +174,6 @@
         }
 
-        return Utils.exists(Utils.filteredCollection(referrers, Way.class), new Predicate<Way>() {
-            @Override
-            public boolean evaluate(final Way otherWay) {
-                return !way.equals(otherWay) && otherWay.hasTag("highway", highway, highway.replaceAll("_link$", ""));
-            }
-        });
+        return Utils.exists(Utils.filteredCollection(referrers, Way.class),
+                otherWay -> !way.equals(otherWay) && otherWay.hasTag("highway", highway, highway.replaceAll("_link$", "")));
     }
 
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/Lanes.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/Lanes.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/Lanes.java	(revision 10608)
@@ -18,4 +18,5 @@
 import org.openstreetmap.josm.tools.Predicates;
 import org.openstreetmap.josm.tools.Utils;
+import org.openstreetmap.josm.tools.Utils.Function;
 
 /**
@@ -51,10 +52,6 @@
             return;
         }
-        final Set<Integer> lanesCount = new HashSet<>(Utils.transform(keysForPattern, new Utils.Function<String, Integer>() {
-            @Override
-            public Integer apply(String key) {
-                return getLanesCount(p.get(key));
-            }
-        }));
+        final Set<Integer> lanesCount = new HashSet<>(Utils.transform(keysForPattern,
+                (Function<String, Integer>) key -> getLanesCount(p.get(key))));
         if (lanesCount.size() > 1) {
             // if not all numbers are the same
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java	(revision 10608)
@@ -2,4 +2,5 @@
 package org.openstreetmap.josm.data.validation.tests;
 
+import static org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker.FixCommand.evaluateObject;
 import static org.openstreetmap.josm.tools.I18n.tr;
 
@@ -787,11 +788,5 @@
                     Main.debug("- Errors: "+pErrors);
                 }
-                final boolean isError = Utils.exists(pErrors, new Predicate<TestError>() {
-                    @Override
-                    public boolean evaluate(TestError e) {
-                        //noinspection EqualsBetweenInconvertibleTypes
-                        return e.getTester().equals(check.rule);
-                    }
-                });
+                final boolean isError = Utils.exists(pErrors, e -> e.getTester().equals(check.rule));
                 if (isError != i.getValue()) {
                     final String error = MessageFormat.format("Expecting test ''{0}'' (i.e., {1}) to {2} {3} (i.e., {4})",
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/OverlappingWays.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/OverlappingWays.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/OverlappingWays.java	(revision 10608)
@@ -8,5 +8,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -175,15 +174,12 @@
     protected static Set<WaySegment> checkDuplicateWaySegment(Way w) {
         // test for ticket #4959
-        Set<WaySegment> segments = new TreeSet<>(new Comparator<WaySegment>() {
-            @Override
-            public int compare(WaySegment o1, WaySegment o2) {
-                final List<Node> n1 = Arrays.asList(o1.getFirstNode(), o1.getSecondNode());
-                final List<Node> n2 = Arrays.asList(o2.getFirstNode(), o2.getSecondNode());
-                Collections.sort(n1);
-                Collections.sort(n2);
-                final int first = n1.get(0).compareTo(n2.get(0));
-                final int second = n1.get(1).compareTo(n2.get(1));
-                return first != 0 ? first : second;
-            }
+        Set<WaySegment> segments = new TreeSet<>((o1, o2) -> {
+            final List<Node> n1 = Arrays.asList(o1.getFirstNode(), o1.getSecondNode());
+            final List<Node> n2 = Arrays.asList(o2.getFirstNode(), o2.getSecondNode());
+            Collections.sort(n1);
+            Collections.sort(n2);
+            final int first = n1.get(0).compareTo(n2.get(0));
+            final int second = n1.get(1).compareTo(n2.get(1));
+            return first != 0 ? first : second;
         });
         final Set<WaySegment> duplicateWaySegments = new HashSet<>();
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/RelationChecker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/RelationChecker.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/RelationChecker.java	(revision 10608)
@@ -29,4 +29,5 @@
 import org.openstreetmap.josm.gui.tagging.presets.items.Roles.Role;
 import org.openstreetmap.josm.tools.Utils;
+import org.openstreetmap.josm.tools.Utils.Function;
 
 /**
@@ -255,10 +256,5 @@
 
             // convert in localization friendly way to string of accepted types
-            String typesStr = Utils.join("/", Utils.transform(types, new Utils.Function<TaggingPresetType, Object>() {
-                @Override
-                public Object apply(TaggingPresetType x) {
-                    return tr(x.getName());
-                }
-            }));
+            String typesStr = Utils.join("/", Utils.transform(types, (Function<TaggingPresetType, Object>) x -> tr(x.getName())));
 
             errors.add(new TestError(this, Severity.WARNING, ROLE_VERIF_PROBLEM_MSG,
@@ -297,10 +293,5 @@
         for (String key : map.keySet()) {
             if (!allroles.containsKey(key)) {
-                String templates = Utils.join("/", Utils.transform(allroles.keySet(), new Utils.Function<String, Object>() {
-                    @Override
-                    public Object apply(String x) {
-                        return tr(x);
-                    }
-                }));
+                String templates = Utils.join("/", Utils.transform(allroles.keySet(), (Function<String, Object>) x -> tr(x)));
 
                 if (!key.isEmpty()) {
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 10607)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 10608)
@@ -6,5 +6,4 @@
 
 import java.awt.GridBagConstraints;
-import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.BufferedReader;
@@ -598,10 +597,5 @@
         testPanel.add(sourcesList, GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(23, 0, 0, 0));
 
-        ActionListener disableCheckActionListener = new ActionListener() {
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                handlePrefEnable();
-            }
-        };
+        ActionListener disableCheckActionListener = e -> handlePrefEnable();
         prefCheckKeys.addActionListener(disableCheckActionListener);
         prefCheckKeysBeforeUpload.addActionListener(disableCheckActionListener);
