简体   繁体   English

遍历数组列表的更有效方法

[英]More efficient way of iterating through on array list

My program takes in thousands of PL/SQL functions, procedures and views, saves them as objects and then adds them to an array list. 我的程序接受数千个PL / SQL函数,过程和视图,将它们另存为对象,然后将它们添加到数组列表中。 My array list stores objects with the following format: 我的数组列表存储以下格式的对象:

ArrayList<PLSQLItemStore> storedList = new ArrayList<>(); 
storedList.add(new PLSQLItemStore(String, String, String,   Long            ));
storedList.add(new PLSQLItemStore(Name,   Type,   FileName, DatelastModified));

What I wanted to do is remove duplicate objects from the array-list based on their Name. 我想做的就是根据名称从数组列表中删除重复的对象。 The older object would be removed based on its dateLastModified variable. 较旧的对象将根据其dateLastModified变量被删除。 The approach i took was to have an outer loop and an inner loop with each object comparing themselves to every other object and then changing the name to "remove" if it was considered to be older. 我采用的方法是有一个外部循环和一个内部循环,每个对象将自己与其他每个对象进行比较,然后将其名称更改为“删除”(如果认为较旧的话)。 The program then does one final pass backwards through the array-list removing any objects whose name is set as "remove". 然后,程序向后进行最后一次遍历数组列表,删除名称设置为“ remove”的所有对象。 While this works fine it seems extremely inefficient. 尽管此方法运行良好,但效率极低。 1000 objects will mean 1,000,000 passes need to be made. 1000个物体将意味着需要进行1,000,000次传递。 I was wondering if someone could help me make it more efficient? 我想知道是否有人可以帮助我提高效率? Thanks. 谢谢。

Sample Input: 输入样例:

storedList.add(new PLSQLItemStore("a", "function", "players.sql", 1234));
storedList.add(new PLSQLItemStore("a", "function", "team.sql", 2345));
storedList.add(new PLSQLItemStore("b", "function", "toon.sql", 1111));
storedList.add(new PLSQLItemStore("c", "function", "toon.sql", 2222));
storedList.add(new PLSQLItemStore("c", "function", "toon.sql", 1243));
storedList.add(new PLSQLItemStore("d", "function", "toon.sql", 3333));

ArrayList Iterator: ArrayList迭代器:

for(int i = 0; i < storedList.size();i++)
{
    for(int k = 0; k < storedList.size();k++)
    {
        if (storedList.get(i).getName().equalsIgnoreCase("remove"))
        {
            System.out.println("This was already removed");
            break;
        }

        if (storedList.get(i).getName().equalsIgnoreCase(storedList.get(k).getName()) &&  // checks to see if it is valid to be removed
           !storedList.get(k).getName().equalsIgnoreCase("remove") &&
           i != k )
        {
            if(storedList.get(i).getLastModified() >= storedList.get(k).getLastModified())
            {
                storedList.get(k).setName("remove");
                System.out.println("Set To Remove");
            }
            else
            {
                System.out.println("Not Older");
            }
        }
    } 
}

Final Pass to remove Objects: 删除对象的最终通行证:

System.out.println("size: " + storedList.size());
for (int i= storedList.size() - 1; i >= 0; i--)
{
    if (storedList.get(i).getName().equalsIgnoreCase("remove"))
    {
        System.out.println("removed: " + storedList.get(i).getName());

        storedList.remove(i);                
    }
}
System.out.println("size: " + storedList.size());

You need to make PLSQLItemStore implement hashCode and equals methods and then you can use Set to remove the duplicates. 您需要使PLSQLItemStore实现hashCodeequals方法,然后可以使用Set删除重复项。

public class PLSQLItemStore {

    private String name;   

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 47 * hash + (this.name != null ? this.name.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final PLSQLItemStore other = (PLSQLItemStore) obj;
        if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name))     {
            return false;
        }
        return true;
    }
}

And then just do Set<PLSQLItemStore> withoutDups = new HashSet<>(storedList); 然后只需执行Set<PLSQLItemStore> withoutDups = new HashSet<>(storedList);

PS equals and hashCode are generated by NetBeans IDE. PS equalshashCode由NetBeans IDE生成。

Put them in a Guava ArrayListMultimap<String,PLSQLItemStore> . 将它们放在Guava ArrayListMultimap<String,PLSQLItemStore>

Add each PLSQLItemStore using name as the key. 使用name作为键添加每个PLSQLItemStore

When you're done adding, loop through the multimap, sort each List with a Comparator<PLSQLItemStore> which sorts by dateLastModified , and pull out the last entry of each List - it will be the latest PLSQLItemStore . 完成添加后,遍历多图,用Comparator<PLSQLItemStore>对每个List进行排序, dateLastModified Comparator<PLSQLItemStore>进行排序,然后拉出每个List的最后一个条目-这将是最新的PLSQLItemStore

Put these entries in another Map<String,PLSQLItemStore> (or List<PLSQLItemStore> , if you no longer care about the name) and throw away the ArrayListMultimap . 将这些条目放在另一个Map<String,PLSQLItemStore> (或List<PLSQLItemStore> ,如果您不再关心名称)中,并丢弃ArrayListMultimap

Building off of Petr Mensik's answer, you should implement equals and hashCode . 基于Petr Mensik的答案,您应该实现equalshashCode From there, you can put items into the map. 从那里,您可以将物品放入地图。 If you come across a duplicate, you can decide then what to do: 如果遇到重复,则可以决定要怎么做:

Map<String, PLSQLItemStore> storeMap = new HashMap<String, PLSQLItemStore>();
for(PLSQLItemStore currentStore : storedList) {

    // See if an item exists in the map with this name
    PLSQLItemStore buffStore = storeMap.get(currentStore.getName();

    // If this value was never in the map, put it in the map and move on
    if(buffStore == null) {
        storeMap.put(currentStore.getName(), currentStore);
        continue;
    }

    // If we've gotten here, then something is in buffStore.
    // If buffStore is newer, put it in the map.  Otherwise, do nothing
    // (this might be backwards --  I didn't quite follow your logic.  
    // Feel free to correct me
    if(buffStore.getLastModified() > currentStore.getLastModified())
        storeMap.put(currentStore.getName(), currentStore);

}

Your map is dup-free. 您的地图没有重复项。 Because Map is a Collection , you can iterate through it later in your code: 由于MapCollection ,因此您可以稍后在代码中对其进行迭代:

for(PLSQLItemStore currentStore : storeMap) {
    // Do whatever you want with your items
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM