我们可以使用给定的索引位置从队列中移除元素吗?

huangapple go评论65阅读模式
英文:

Can we remove element from a queue using given index position?

问题

public static void deleteFromQueue(PassengerQueue passengerQueue){

    //passengerQueue.dequeue();
    Scanner scan = new Scanner(System.in);
    System.out.print("请输入乘客姓名:");
    String name = scan.nextLine();
    for (int i=0; i<passengerQueue.getPassenger().length; i++){
        if (passengerQueue.getPassenger()[i].getName().equals(name)){
            //
        }
    }
}

这是我的移除方法


<details>
<summary>英文:</summary>

I implemented a queue using array. Now I want to remove a element by searching, if the element were there it must be removed from the queue.
```java
public static void deleteFromQueue(PassengerQueue passengerQueue){

    //passengerQueue.dequeue();
    Scanner scan = new Scanner(System.in);
    System.out.print(&quot;please Enter the Passenger name: &quot;);
    String name = scan.nextLine();
    for (int i=0; i&lt;passengerQueue.getPassenger().length; i++){
        if (passengerQueue.getPassenger()[i].getName().equals(name)){
            //
        }
    }
}

here my method of removing

答案1

得分: 1

为什么您特别想要使用一个 array。以下附有使用 ArrayList 的示例:

    package stackoverflow;

    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;

    import java.util.ArrayList;
    import java.util.Iterator;

    public class QuickTest {
    
        @Test
        public void test() throws Exception {
            PassengerQueue passengerQueue = new PassengerQueue();
            passengerQueue.add(new Passenger("testName1"));
            passengerQueue.add(new Passenger("testName2"));
            Assertions.assertEquals(2, passengerQueue.size());
        
            PassengerUtil.removeByName(passengerQueue, "testName1");
            Assertions.assertEquals(passengerQueue.size(), 1);
        
            System.out.println("All done");
        }
    
        private static class PassengerUtil {
           
            /** @param passengerQueue    Modified by reference. **/
            private static void removeByName(PassengerQueue passengerQueue, String specifiedName) {
                // Using an Iterator so that I don't trigger ConcurrentModificationException.
                for (Iterator<Passenger> it = passengerQueue.iterator() ; it.hasNext() ; ) {
                    Passenger currPassenger = it.next();
                    if (currPassenger.getName().equals(specifiedName)) {
                        it.remove();
                    }
                }
            }
        }
    
        private class PassengerQueue extends ArrayList<Passenger> {
        }
    
        private class Passenger {
        
            private String name;
        
            public Passenger(String name) {
                if (name == null) {
                    throw new NullPointerException("The " + Passenger.class.getSimpleName() + " cannot have a Name equal to NULL!");
                }
                this.name = name;
            }
        
            public String getName() {
                return this.name;
            }
        }
    }

请注意以下内容:

  • 我的 PassengerQueue 对象扩展了 ArrayList。因此,通过扩展 ArrayList,我就有了一个类型安全的 Passenger 列表 - 我不需要做其他任何事情。

  • 我使用 Iterator 来遍历列表。它比普通的 for-each 循环 稍微冗长,但是它是不触发 ConcurrentModificationException 的必要条件。在遍历列表的同时从列表中删除元素时,Java 并不总是喜欢这样做。(也许简单的示例不会触发 ConcurrentModificationException

  • 您将列表称为 PassengerQueue。请注意,Java 确实有 Queue(https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html)集合。类似于我扩展 ArrayList,您可以查看 Queue 的子类,并在需要使您的 Collection 函数像队列一样时扩展它。

  • 您的代码和我的代码目前都可以从列表中删除具有相同名称的 Passenger

  • 您的问题标题问如何通过索引位置从 array 中删除。您可以考虑将 Apache Commons Lang 项目添加到类路径中,并使用其中的方法,如 ArrayUtils

实际上,我的答案可以进一步改进,甚至不需要使用 Iterator

    private static class PassengerUtil {
            
        /** @param passengerQueue    Modified by reference. **/
        private static void removeByName(PassengerQueue passengerQueue, String specifiedName) {
            passengerQueue.removeIf(currPassenger -> currPassenger.getName().equals(specifiedName));
        }
    }

有关后一个代码示例的更多信息,请查看 此处

英文:

Why do you specifically want to use an array. Please find an example attached using an ArrayList:

    package stackoverflow;

    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;

    import java.util.ArrayList;
    import java.util.Iterator;

    public class QuickTest {
    
        @Test
        public void test() throws Exception {
            PassengerQueue passengerQueue = new PassengerQueue();
            passengerQueue.add(new Passenger(&quot;testName1&quot;));
            passengerQueue.add(new Passenger(&quot;testName2&quot;));
            Assertions.assertEquals(2, passengerQueue.size());
        
            PassengerUtil.removeByName(passengerQueue, &quot;testName1&quot;);
            Assertions.assertEquals(passengerQueue.size(), 1);
        
            System.out.println(&quot;All done&quot;);
        }
    
        private static class PassengerUtil {
           
            /** @param passengerQueue    Modified by reference. **/
            private static void removeByName(PassengerQueue passengerQueue, String specifiedName) {
                // Using an Iterator so that I don&#39;t trigger ConcurrentModificationException.
                for (Iterator&lt;Passenger&gt; it = passengerQueue.iterator() ; it.hasNext() ; ) {
                    Passenger currPassenger = it.next();
                    if (currPassenger.getName().equals(specifiedName)) {
                        it.remove();
                    }
                }
            }
        }
    
        private class PassengerQueue extends ArrayList&lt;Passenger&gt; {
        }
    
        private class Passenger {
        
            private String name;
        
            public Passenger(String name) {
                if (name == null) {
                    throw new NullPointerException(&quot;The &quot; + Passenger.class.getSimpleName() + &quot; cannot have a Name equal to NULL!&quot;);
                }
                this.name = name;
            }
        
            public String getName() {
                return this.name;
            }
        }
    }

Please note the following:

  • My PassengerQueue object extends ArrayList. So I have a type-safe list of Passengers just by extending ArrayList - I don't need to do anything else.

  • I use an Iterator to iterate over the list. Its a bit more verbose than your normal for-each loop, but its necessary to not trigger a ConcurrentModificationException. Java doesn't always like when you iterate over a list and then for example delete things from that list while you're iterating over it. (Maybe simple examples won't trigger the ConcurrentModificationException)

  • You called your list PassengerQueue. Please note that Java does have Queue(https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html) collections. Similar to me extending ArrayList you can look at Queue subclasses and extend that instead if you really need your Collection to function like a queue.

  • Your code, and mine, can currently delete multiple elements from the list if the list contains Passengers with the same name.

  • Your question title asked about deleting from an array using an index position. You can consider adding the Apache Commons Lang project to your classpath and using methods from their ArrayUtils

Actually, my answer can be improved to not even use an Iterator:

    private static class PassengerUtil {
            
        /** @param passengerQueue    Modified by reference. **/
        private static void removeByName(PassengerQueue passengerQueue, String specifiedName) {
            passengerQueue.removeIf(currPassenger -&gt; currPassenger.getName().equals(specifiedName));
        }
    }

Some reading on the latter code example here.

答案2

得分: 1

一个'Queue'被定义为一种数据结构,它保存一个项目序列,您只能将某些东西添加到末尾('尾部'),并且可以从开头('头部')取出某些东西。有时会说您可以获取序列的当前大小,询问序列是否为空,并且您可以查看('peek')第一个项目而不将其取出。

那就是基础。而且您可以用不同的方式实现它。

在Java中有一个接口(java.util.Queue),提供了上述基本功能。所以当您声明

java.util.Queue myQueue = 

然后您不能搜索队列中的项目并将其删除(好吧,您可以逐个从队列中取出所有元素,然后再添加要保留的元素,但这很繁琐)。

但是java.util.Queue的实现是java.util.LinkedList,而列表是可以搜索的。

所以您写了

java.util.Queue myQueue = new java.util.LinkedList();

并且由于您现在知道您的队列的实现实际上是一个列表,您可以写成


for (var i = ((java.util.List) myQueue).iterator(); i.hasNext(); ) {
    if (matchesCriteriaForRemoval(i.next())) i.remove();
}

但这只能工作是因为您知道myQueue的一些实现细节 - 但这正是您在选择将其定义为java.util.Queue时想要隐藏的内容。

因此,当您必须能够从您的PassengerQueue中删除条目时,该数据结构应该提供一种方法来实现此操作,而不是揭示其内部实现。

这意味着您的代码应该如下所示:

public static void deleteFromQueue(PassengerQueue passengerQueue) {
    Scanner scan = new Scanner(System.in);
    System.out.print("请输入乘客姓名:");
    String name = scan.nextLine();
    passengerQueue.removeByName(name);
}

方法PassengerQueue.removeByName()的实现方式取决于PassengerQueue的内部实现;如果它使用名为passengersjava.util.List来存储乘客,它可能如下所示:

public final void removeByName(final String name) {
    for (var i = passengers.iterator(); i.hasNext(); ) {
        if (passengerNameMatches(name, i.next())) i.remove();
    }
}

如果您为乘客使用另一个容器,那么该删除方法必须以不同的方式实现…

显然,我省略了所有错误处理,集合是泛型类型,但由于简洁起见,我将它们用作原始类型。

英文:

A 'Queue' is defined as a data structure that holds a sequence of items where you can only add something to the end (the 'tail') and where you can take something from the beginning, the 'head'. And sometimes it is said that you can get the current size of the sequence, ask whether the sequence is empty, and that you can look ('peek') at the first item without taking it.

That's the basics. And you can implement that in various ways.

There is an interface in Java (java.util.Queue) that provides the basic features described above. So when you declare

java.util.Queue myQueue = …

then you cannot search your queue for an item and remove it (ok, you can take all elements from your queue, one by one, and add again those you want to keep, but that's tedious).

But the implementation for java.util.Queue is java.util.LinkedList, and a list can be searched.

So you write

java.util.Queue myQueue = new java.util.LinkedList();

and as you now know that the implementation of your queue is in fact a list, you can write

…
for( var i = ((java.util.List) myQueue).iterator(); i.hasNext(); )
{
if( matchesCriteriaForRemoval( i.next() ) i.remove();
}
…

But this works only because you know some implementation details of myQueue – but that was what you want to hide when you chose to define it as java.util.Queue.

So when you have to be able to remove entries from your PassengerQueue, that data structure should provide a method to do so instead of revealing its internal implementation.

This means your code have to look like this:

public static void deleteFromQueue( PassengerQueue passengerQueue )
{
Scanner scan = new Scanner( System.in );
System.out.print( &quot;please Enter the Passenger name: &quot; );
String name = scan.nextLine();
passengerQueue.removeByName( name );
}

How this method PassengerQueue.removeByName() is implemented depends from the internal implementation of PassengerQueue; if it uses the java.util.List with the name passengers to store the passengers, it may look like this:

public final void removeByName( final String name )
{
for( var i = passengers.iterator(); i.hasNext(); )
{
if( passengerNameMatches( name, i.next() ) ) i.remove();
}
}

If you use another container for your passengers, that removal method has to be implemented differently …

Obviously I omitted all error handling, and the collections are generic types, but I used them as raw because of brevity.

huangapple
  • 本文由 发表于 2020年4月11日 13:46:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/61152626.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定