I have this code working with a for loop and steam, but I was wondering I can improve it using two streams. Here I want to replace the for loop with a stream and would like to get a list of String that the method returns.
public class City { final int x; final int y; final String name; public City(String name, int x, int y) { this.name = name; this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } public String getName() { return name; } } import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; public class Test { public static boolean cityFilter(City city, City c) { return !city.getName().equals(c.getName()) && (city.getX()==c.getX() || city.getY()==c.getY())?true:false; } public static int compareCities(City c, City c1, City c2) { int dis1 = Math.abs(c.getX() - c1.getX()) + Math.abs(c.getY() - c1.getY()); int dis2 = Math.abs(c.getX() - c2.getX()) + Math.abs(c.getY() - c2.getY()); return dis1==dis2?c.getName().compareTo(c2.getName()):dis1-dis2; } public static List<String> filterAndFindCities(List<String> c, List<Integer> x, List<Integer> y, List<String> q) { Map<String, City> cityMap = IntStream.range(0, c.size()).boxed().collect(Collectors.toMap(c::get, i-> new City(c.get(i), x.get(i), y.get(i)))); List<String> rst = new ArrayList<String>(); //====How can I replace this for loop with a stream and get a list of String?=== for (String s : q) { City givenCity = cityMap.get(s); City nearest = cityMap.values().stream().filter(p -> cityFilter(givenCity, p)) .sorted((c1, c2) -> compareCities(givenCity, c1, c2)) .findFirst().orElse(null); String nearestCity = nearest != null ? nearest.getName() : "EMPTY"; rst.add(nearestCity); } return rst; } }
Advertisement
Answer
I was able to find a quick and dirty solution, of course not the best, but sure I can improve this.
public static List<String> filterAndFindCities(List<String> c, List<Integer> x, List<Integer> y, List<String> q) { Map<String, City> cityMap = IntStream.range(0, c.size()).boxed() .collect(Collectors .toMap(c::get, i -> new City(c.get(i), x.get(i), y.get(i)))); return q.stream() .map(name ->cityMap.values().stream() .filter(p -> cityFilter(cityMap.get(name), p)) .sorted((c1, c2) -> compareCities(cityMap.get(name), c1, c2)) .findFirst().orElse(null)) .map(p->p!=null?p.getName():"EMPTY") .collect(Collectors.toList()); }