按两个唯一属性过滤Java List

时间:2017-06-28 10:18:18

标签: java arraylist sortedlist

请我尝试通过两个独特的属性过滤我从DB查询的列表。以下是该表的示例:

id | seatNo | time | type
=== ======== ====== =====
1  |   1    |   1  |  1  *
2  |   2    |   1  |  1
3  |   1    |   2  |  1  *
4  |   2    |   2  |  1
5  |   3    |   1  |  2  *
6  |   4    |   1  |  2

带星号(*)的行是时间和类型的唯一值。我如何编写一个循环,按时间和类型过滤此列表中的唯一对象。我尝试过这样的事情:

int currentTime = 0;
int currentType = 0;
List<Bus> sortedBuses = new ArrayList<>();
for (Bus bus : allSeats) {
    if (bus.getTime()!= currentTime && bus.getType != currentType) {
        sortedBuses.add(bus);
    }
    currentId = bus.getTime();
    currentType = bus.getType();
}

但这不能正确过滤。我只能得到像时间和时间这样的独特价值观。类型是平等的。任何有助于我解决这个问题的想法都是受欢迎的。

4 个答案:

答案 0 :(得分:0)

由于您希望按唯一的timetype字段进行过滤,因此我引入了一个字符串,可以将其读作

<time>_<type>

然后现在更容易找到独特的元素:

List<String> foundTimeType = new ArrayList<String>(); // represents a list of known types
List<Bus> sortedBuses = new ArrayList<>();
for (Bus bus : allSeats) {
    String timeType = "" + bus.getTime() + "_" + bus.getType();
    // only add if timeType is not present in foundTimeType list
    if (! foundTimeType.contains(timeType)) {
        foundTimeType.add(timeType); // to keep it unique
        sortedBuses.add(bus);
    }
}

答案 1 :(得分:0)

您必须对存储在sortedBuses

中的总线进行过滤
List<Bus> sortedBuses = new ArrayList<Bus>();

outerloop:
for (Bus bus : allSeats) {
   for (Bus sorted : sortedBuses)
      if (bus.getTime()==sorted.getTime() && bus.getType == sorted.getType)
        continue outerloop;
   sortedBuses.add(bus);
}

答案 2 :(得分:0)

我不知道,也许不是你想要的,但是你可以使用 HashSet 代替ArrayList,在java中这个数据结构默认不插入副本。当然,这种机制仅适用于基本类型,对于自定义对象(作为您的),您应该覆盖哈希码,并使用等于方法来使机制起作用。

以下是您的案例示例:

public class Bus {

    private int type;

    private int time;

    public Bus(int type, int time) {
        // TODO Auto-generated constructor stub
            this.type = type;
            this.time = time;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public int getTime() {
        return time;
    }

    public void setTime(int time) {
        this.time = time;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + time;
        result = prime * result + type;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Bus other = (Bus) obj;
        if (time != other.time)
            return false;
        if (type != other.type)
            return false;
        return true;
    }
}

你的主要是:

import java.util.HashSet;


public class Main {

    public Main() {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        HashSet<Bus> buses = new HashSet<Bus>();
        Bus b1 = new Bus(1, 1);
        Bus b2 = new Bus(1, 1);
        Bus b3 = new Bus(2, 1);
        Bus b4 = new Bus(2, 1);
        buses.add(b1);
        buses.add(b2);
        buses.add(b3);
        buses.add(b4);

        System.out.println("size: "+buses.size());
 for(Bus bus : buses) {
            System.out.println(bus.getTime()+" "+bus.getType());
            }


    }

}

输出:

size: 2
1 1
1 2

此外,如果你的对象(Bus)实现了Comparable,这意味着你将覆盖方法compareTo(Object o),而不是HashSet,你可以使用 TreeSet ,你将获得均匀的排序数据结构

答案 3 :(得分:0)

这可以使用流API在一行中解决,通过将时间和类型收集到地图的键中然后简单地导出值。密钥将包含时间和类型。

该行将是:

buses.stream().collect(toMap(b -> String.format("%d_%d", b.getType(), b.getTime()), p -> p, (p, q) -> p))
                    .values();

这是一个简单的测试:

List<Bus> buses = Arrays.asList(new Bus(1, 1, 1), new Bus(2, 1, 1),
                new Bus(3, 2, 1), new Bus(4, 2, 1),
                new Bus(5, 1, 2), new Bus(6, 1, 2));
Collection<Bus> res = buses.stream().collect(toMap(b -> String.format("%d_%d", b.getType(), b.getTime()), p -> p, (p, q) -> p))
                .values();
res.forEach(System.out::println);

这会在控制台上打印出来:

> Bus{id=1, type=1, time=1}
> Bus{id=5, type=1, time=2}
> Bus{id=3, type=2, time=1}