Java初学者问题:在ArrayList中查找下一个可用ID的方法

时间:2019-05-29 13:36:54

标签: java

本练习给出了五个建议:制定一种在成员对象的ArrayList中查找下一个可用成员ID的方法。在创建新成员时,我会手动创建成员ID,并且我始终可以假定成员已按ID顺序排列。 例如:如果我有4个ID从0-3的成员,并且我删除了第二个成员,则该方法应返回1。

这是我现在遇到的麻烦部分:

public int getNextID (){
    int i;
    for(i = 0; i < members.size(); i++){
        if(i == members.get(i).getID()){
            i++;



        }
        else if(i != members.get(i).getID()){
            System.out.println("Next available ID:  " + i);

        } else {
            System.out.println("Next available ID: " + members.size());
            break;
        }
    }
    return i;
} 

2 个答案:

答案 0 :(得分:0)

对于列表,请使用size()来获取元素数。(它还会为您提供最后一个但使用1个索引)。 索引从0开始,并在添加或删除元素时自动调整。 因此,您无需手动跟踪索引。
请注意,当您使用方法add(index, element)添加到列表时,索引应始终小于或等于size() _ methods return。

    List<String> l = new ArrayList<String>();
    l.add("a"); //auto index 0
    l.add("b"); //auto index 1
    l.add("c"); //auto index 2
    System.out.println(l.size()); //3 and it's also next_available for add at bottom
    l.remove(1);
    l.forEach(System.out::println); //a c
    System.out.println(l.size()); // 2
    System.out.println(l.get(0)); //a
    System.out.println(l.get(1)); //c adjusted index from 2 to 1 after remove
    l.add(2,"d");
    System.out.println(l.size()); //3
    l.add(4,"e"); //error  java.lang.IndexOutOfBoundsException: Index: 4, Size: 3

请参阅@Sunchezz和@Evan答案以获取完整的解决方案。

答案 1 :(得分:0)

此解决方案从列表中提供了一个新的会员ID,其中所有MemberItem均按ID排序。列表中的项目0必须具有ID0。项目1-> ID 1。 新ID将始终是当前未分配的最低可用ID。


解决方案1 ​​

public int getNextID (){
    for(int i = 0; i < members.size(); i++){
        if(i < members.get(i).getID()){
            System.out.println("Next available ID:  " + i);
            // at this point we know this is the next id.
            // we can leave the method and return the next ID.
            return i;
        }
    }
    // we did not leave the loop (and method), because all id's are assigned.
    System.out.println("Next available ID:  " + members.size());
    return members.size();
}

解决方案2(Java 1.8+流)

如果您喜欢2行Java 8流解决方案,也可以使用以下方法:

public int getNextID() {
   Member m = members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().orElse(null);
   return (m != null ? members.indexOf(m) : members.size());
}

解决方案3(Java 1.8+流)

或1行流解决方案:

public int getNextID() {
   return members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().map(m2 -> members.indexOf(m2)).orElse(members.size());
}

要对您的代码说些什么: 您将i增加两次。 一次在for语句中以i++结尾,在下面的两行再次以i++结尾。 这样,您将跳过索引1。如果第一个成员具有与索引相同的ID。


时间和测试

适合对三种解决方案之间的时间比较感兴趣的任何人。这是我使用Java1.8的时间:

|----------------------------------------------------------------------|
| 10000 Items, Free Position 9998    | 10000 Items, Free Position 1    |
|----------------------------------------------------------------------|
| Solution1: ~2ms                    |  Solution1: ~0.005ms            |  
| Solution2: ~65ms                   |  Solution2: ~0.05ms             |
| Solution3: ~60ms                   |  Solution3: ~0.06ms             |
|----------------------------------------------------------------------|

在机器上执行它的代码。肯定会导致计时结果不同,但是比例应该保持不变。

import java.util.ArrayList;
import java.util.List;

public class Test {
    private static List<Member> members = new ArrayList<>();

    public static void main(String[] args) {
        members = getTestList(10000);

        warmUp();

        members.remove(9998);
        testSolutions();
        members.remove(1);
        testSolutions();

    }

    private static void warmUp() {
        for (int i = 0; i < 5; i++) {
            for (Member m : members) {
                // warm up cpu for iteration
            }
            members.forEach(Member::getID);
        }
    }

    private static void testSolutions() {
        long start = System.nanoTime();
        int result1 = getNextID();
        System.out.println("#1 Iterative result: " + result1 + " | in " + (System.nanoTime() - start) / 1000000.0 + "ms");
        start = System.nanoTime();
        Member m = members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().orElse(null);
        int result2 = m != null ? members.indexOf(m) : members.size();
        System.out.println("#2 Stream Result: " + result2 + " | in " + ((System.nanoTime() - start) / 1000000.0) + "ms");
        start = System.nanoTime();
        int result3 = members.stream().filter(member -> member.getID() != members.indexOf(member)).findFirst().map(m2 -> members.indexOf(m2)).orElse(members.size());
        System.out.println("#3 Stream Result: " + result3 + " | in " + ((System.nanoTime() - start) / 1000000.0) + "ms");
    }

    private static int getNextID() {
        for (int i = 0; i < members.size(); i++) {
            if (i < members.get(i).getID()) {
                return i;
            }
        }
        return members.size();
    }

    private static List<Member> getTestList(int count) {
        List<Member> members = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            members.add(new Member(i));
        }
        return members;
    }

    private static class Member {
        private int id;

        public Member(int id) {
            this.id = id;
        }

        private int getID() {
            return id;
        }
    }
}