2016-01-28 199 views
-2

好日子搜索在ArrayList中的特定对象,通过属性

想象我有以下代码: (这些显然不是所有的属性)

class Owner { 
    private String name; 
} 

class Car { 
    private Owner owner; 
    private String brandName; 

    public boolean isClean() { // not included in the contructor 
     return false; 
    } 

class FuelCar extends Car { 
    private String fuelType; 

    public boolean isClean() { 
     if (fuelType.equals("Diesel")){ 
      return false; 
     } else { 
      return true; 
    } 
} 

class ElectricCar extends Car { 
    private int batteryLevel; 

    public boolean isClean() { 
     return true; 
    } 
} 

的对象添加到一个ArrayList:

ArrayList<Car> cars = new ArrayList<>(); 

实例:

cars.add(new Auto("Audi", new Owner("Peter"))); 
cars.add(new Auto("Fiat", new Owner("Rob"))); 
cars.add(new Auto(Mercedes, null)); 
cars.add(new ElectricCar(10, "Opel ", new Owner("Unknown"))); 
cars.add(new ElectricCar(100,"Google", new Owner("Google"))); 
cars.add(new FuelCar("diesel", "Seat", new Owner("Tom"))); 
cars.add(new FuelCar("gasonline", "Smart", new Owner("Marcel"))); 

现在的问题是:

  1. 我怎样才能让一个方法,所以我只列出其中具有值isClean“真”的所有汽车;

  2. 如何使具有以下签名的方法: 公共静态无效printCarsSpecific(ArrayList的汽车,字符串fuelType) 因此,举例来说,如果我把在: printCarsSpecific(“汽油”); 打印ArrayList时只显示那些汽车。

PS:这不是功课。只为教育 我自己输入了上面的代码,并没有复制和粘贴,因为它会变大。

我尝试以下方法:

public static void printBedrijfsautosMetType(ArrayList<Auto> autos, String brandstof) { 
    Iterator<Auto> iter = autos.iterator(); 
    while (iter.hasNext()) { 
     Auto auto = iter.next(); 

     if (auto instanceof BrandstofAuto) { 
      String brandstof1 = ((BrandstofAuto) auto).getBrandstof(); 
      if (!brandstof1.equals(brandstof) || brandstof1 == null) { 
       iter.remove(); 
      } 
     } 
     for (int i = 0; i < autos.size(); i++) { 
      System.out.println(autos.get(i)); 
     } 

    } 
} 

public static void printSchoneAutos(ArrayList<Auto> autos) { 
     Iterator<Auto> iter = autos.iterator(); 
     while (iter.hasNext()) { 
      Auto auto = iter.next(); 
      if (auto instanceof BrandstofAuto) { 
       boolean isschoon = ((BrandstofAuto) auto).isSchoon(); 
       boolean isschoon3 = auto.isSchoon(); 
       if (isschoon3 == false || isschoon == false) { 
        iter.remove(); 
       } 
      } 
      for (int i = 0; i < autos.size(); i++) { 
       System.out.println(autos.get(i)); 
      } 
     } 
    } 

我想我没有删除这些项目,因为我已经通过例子在这里看到。

+0

你尝试过什么吗? – proskor

+0

@ R.Schouten您至少应该首先缩进您的代码。此外,你的语法是错误的,为什么像'class'和'private'这样的词汇是大写的?在我看来,你甚至不知道基本知识。也许你应该发布你到目前为止尝试过的东西。 – user3437460

+3

这确实看起来像一个家庭作业... –

回答

0

这似乎是一个家庭作业,但我会咬。

最简单的方法是迭代原始列表并从中选择匹配的项目。

ArrayList<Car> cleanCars = new ArrayList<Car>(); 
for (Car car : scars) { 
    if (car.isClean()) { 
     cleanCars.add(car); 
    } 
} 

一个显然会创建一个对象来包装汽车的收藏。也许类似CarCollection,这本身就换一个集合对象像ArrayList


该问题的第二部分看起来像是XY Problem。你为什么要混合过滤收集的汽车物体并将其打印出来的逻辑? (除了,你知道,如果它是一项家庭作业)。数据排序逻辑和表示逻辑应该尽可能分开。

取而代之的是以下内容:

public static void printCarsSpecific(ArrayList Cars, String fuelType)

为什么不能有一个过滤器的汽车名单的方法?

public static ArrayList<Car> getCarsByFuelType(ArrayList cars, String fuelType)

然后,当你已经被过滤的集合,那么你可以做你想和他们(即打印出来)是什么?

下面是我如何实现它。我有一个CarCollection类,它包装并提供您在私人ArrayList之上所需的访问方法。喜欢这个。汽车的

public class CarCollection { 
    private ArrayList<Car> carList; 

    public void add(Car car) { 
     carList.add(car); 
    } 

    public CarCollection getCleanCars() { 
     CarCollection cleanCars = new CarCollection(); 
     for (Car car : this.cars) { 
      if (car.isClean()) { 
       cleanCars.add(car); 
      } 
     } 
     return cleanCars; 
    } 

    public CarCollection getCarsByFuelType(String fuelType) { 
     CarCollection filteredCars = new CarCollection(); 
     for (Car car : this.cars) { 
      if (car instanceof FuelCar) { 
       if (car.fuelType.equals(fuelType)) { 
        filteredCars.add(car); 
       } 
      } 
     } 
     return filteredCars; 
    } 
} 
0

硬编码过滤列表:

public static List<Car> filterCleanFuelCars(List<Car> cars) { 
    List<Car> filtered = new LinkedList<>(); 
    for (Car c : cars) { 
     if (c instanceof FuelCar) { 
      FuelCar fuelCar = (FuelCar) c; 
      if (fuelCar.isClean()) { 
       filtered.add(fuelCar); 
      } 
     } 
    } 
    return filtered; 
} 

滤波基于自定义条件汽车的列表(硬编码条件由谓词替换):

public static List<Car> filterCars(List<Car> cars, Predicate<Car> condition) { 
    List<Car> filtered = new LinkedList<>(); 
    for (Car c : cars) { 
     if (condition.apply(c)) { 
      filtered.add(c); 
     } 
    } 
    return filtered; 
} 

相同如上Stream

public static List<Car> filterCars(List<Car> cars, Predicate<Car> condition) { 
    return cars.stream() 
       .filter(condition) 
       .collect(Collectors.toList()); 
} 
使用的

示例:

List<Car> cleanCars = filterCars(cars, new Predicate<Car>() { 
    @Override 
    public boolean apply(Car c) { 
     return c.isClean(); 
    } 
}); 

这可以通过lambda表达式(取代匿名类)被缩短

List<Car> cleanCars = filterCars(cars, (Car c) -> c.isClean()); 

如果需要更多的线,以决定该过滤器是否适用于汽车,你可以这样写:

List<Car> cleanFuelCars = filterCars(cars, (Car c) -> { 
    if (c instanceof FuelCar) { 
     FuelCar fuelCar = (FuelCar) c; 
     return c.isClean(); 
    } 
    return false; 
}); 

由于包含在列表中的汽车并非全部都是FuelCar,首先需要检查车辆是否是FuelCar的实例,之后需要将该车投入FuelCar型,最后检查fuelType属性的值。

。注意,String值不能被使用==操作者检查是否相等,因为String不是原始数据类型int, long, float, double它们总是由值(当你通过int一种方法,然后int传递被复制到方法的局部变量 - 参数中)。通过==比较像String这样的对象只检查引用的相等性,即检查两个对象是否指向内存中的同一对象 - 对象始终是引用(地址)传递的。总之,当你使用字符串时总是使用equals方法。

public static void printCarsSpecific(List<Car> cars, String fuelType) { 
    for (Car c : cars) { 
     if (c instanceof FuelCar) { 
      FuelCar fuelCar = (FuelCar) c; 
      if (fuelCar.fuelType.equals(fuelType)) { 
       System.out.println(fuelCar); 
      } 
     } 
    } 
} 

您也可以重写printCarsSpecific更通用的方法,通过使用filterCars方法:

public static void printCarsSpecific(List<Car> cars, Predicate<Car> p) { 
    List<Car> filtered = filterCars(cars, p); 
    for (Car c : filtered) { 
     System.out.println(c); 
    } 
} 

要打印汽油燃料的汽车,你可以这样写:

printCarsSpecific(cars, (Car c) -> { 
    if (c instanceof FuelCar) { 
     FuelCar fuelCar = (FuelCar) c; 
     retur fuelCar.fuelType.equals("gasoline"); 
    } 
    return false; 
}); 
0

如果您使用的是Java 8你可以使用花哨的流,如:

List<Car> cleanCars = carList.stream().filter(car -> car.isClean()).collect(Collectors.toList()); 

List<Car> carsFilteredOnFuelType = carList.stream().filter(car -> fueltype.equals(car.fueltype)).collect(Collectors.toList)); 
0

如果您不需要,我建议您不要将变量声明为ArrayList。抽象越大,代码越一般,因此程序越强大。请看下面的例子:

ArrayList<Car> cars = new ArrayList<>(); 

为什么你不得不说,carsArrayList?您只需在实例化时指定确切的类型。这是优越:

AbstractList<Car> cars = new ArrayList<Car>(); 

ArrayListimplementsAbstractList,你可能会决定稍后切换到cars另一种类型的AbstractList实施。

此外,阅读/观看一些教程,因为即使使用最基本的语法,您也在苦苦挣扎。

现在让我们看看你的问题。你的第一个问题要求一种只列出清洁cars的方法。这个任务不是原子的,你需要分离任务。首先,获得cars的干净子集是很好的。即使您不打算列出它们,这种类型的任务也可能很有用。因此,让我们独立实施:

public static AbstractList<Car> getCleanCars(AbstractList<Car> cars) { 
    AbstractList<Car> cleanCars = new ArrayList<Car>(); 
    for (Car car : cars) { 
     if (car.isClean()) { 
      cleanCars.add(car); 
     } 
    } 
    return cleanCars; 
} 

然后您需要一种显示cars的方法。让我们假设它看起来像这样:

public static void displayCars(AbstractList<Car> cars) { 
    //Display the cars 
} 

您需要调用displayCars这样的:Car.displayCars(Car.getCleanCars(cars))

你的第二个问题是不合逻辑的,因为你要调用使用单个参数的两个参数中声明的方法。由于你的代码充满了错误,所以它真的无法读取,所以我无法为你提供帮助,但是,如果某种燃料类型可以从Car对象中确定,那么您需要按照图示反复显示汽车列表而不是调用isClean,则需要使用.equals()方法将Car的燃料类型作为String与接收的参数进行比较。