0

I have some questions below code block in Java:

  1. Output gives 5 times New Delhi. I wonder why the other map elements are not listed and the last one is repeated constantly? The output is:

` City Code: DEL --> City Name: New Delhi

City Code: DEL --> City Name: New Delhi
City Code: DEL --> City Name: New Delhi
City Code: DEL --> City Name: New Delhi
City Code: DEL --> City Name: New Delhi
  1. For example if the user gives 3 for the first input (for the number of elements), program takes only 2 element to the array then it stops.
  2. This code block never stops, how can I stop the program?

The code block:

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
public static void main(String[] args) {



    ExecutorService executorService = Executors.newFixedThreadPool(5);

    Map<String, City> map = new HashMap<>();

    City moscow = new Moscow("Moscow", "MOW");
    map.put(moscow.getCityCode(), moscow);
    City london = new London("London", "LON");
    map.put(london.getCityCode(), london);
    City newyork = new NewYork("New York", "NYC");
    map.put(newyork.getCityCode(), newyork);
    City berlin = new Berlin("Berlin", "BER");
    map.put(berlin.getCityCode(), berlin);
    City newdelhi = new NewDelhi("New Delhi", "DEL");
    map.put(newdelhi.getCityCode(), newdelhi);


    List<City> cityByCode = new ArrayList<>(map.values());
    Collections.sort(cityByCode);
    for (int i = 0; i < cityByCode.size(); i++) {
        System.out.println("City Code: " + City.getCityCode() + " --> City Name: " + City.getCityName());
    }


    Scanner s = new Scanner(System.in);
    System.out.println("Select a minimum of three and a maximum of five cities listed above. First of all, please specify the number of cities you will choose: ");
    int length = s.nextInt();
    System.out.println("Please enter " + length + " city codes ");
    String[] myArray = new String[length];
    for (int i = 0; i < length; i++) {
        myArray[i] = s.nextLine();
    }

    for (String list : myArray) {
        switch (list) {
            case "MOW":
                executorService.execute(new SimpleThread(moscow));
                break;
            case "LON":
                executorService.execute(new SimpleThread(london));
                break;
            case "NYC":
                executorService.execute(new SimpleThread(newyork));
                break;
            case "BER":
                executorService.execute(new SimpleThread(berlin));
                break;
            case "DEL":
                executorService.execute(new SimpleThread(newdelhi));
                break;
        }
    }
}

}

nabayram
  • 49
  • 5
  • 3
    Could you provide the implementation of `getCityCode()` and `getCityName()` methods? Are the `city` and `code` fields `static`? Are the methods `getCityCode()` and `getCityName()` `static`? If yes, then there is the problem. – kasptom Dec 06 '20 at 07:15
  • When posting on Stack Overflow, better to whittle your code down to the minimum needed to show your issue. And, you'll likely solve your own problem that way as well. – Basil Bourque Dec 06 '20 at 07:18
  • For your second question: your code uses `Scanner.nextLine()` after `Scanner.nextInt()` which is problematic. See https://stackoverflow.com/a/13102066/5646962 for more background and possible solutions – Thomas Kläger Dec 06 '20 at 07:20
  • For the third question: you have to shutdown the `ExecutorService`: `executorService.shutdown();` – Thomas Kläger Dec 06 '20 at 07:28
  • This line is wrong `System.out.println("City Code: " + City.getCityCode() + " --> City Name: " + City.getCityName());`. You are supposed to traverse `cityByCode`, something like `cityByCode.get(i).xxx` – Agus Dec 06 '20 at 07:36
  • Without the City class we cannot fully debug this. Please do not handicap the volunteers trying to help you. (I do believe that the static methods City.getCityCode() and City.getCityName() are the big problems.) – NomadMaker Dec 06 '20 at 10:58

1 Answers1

3

You have not disclosed enough code to solve your specific problems. But here are some tips and some example code.

I'm no expert with Scanner, but it seems you should be using … s.next(); rather than … s.nextLine();.

Always shutdown your executor service before your app ends. Otherwise the backing thread pool may continue indefinitely, like a zombie ‍♂️.

Using modern Java can shorten your code. For example Map.of, switch expressions, and try-with-resources. The new record feature defines a class for immutable objects while synthesizing the getter, toString, equals, and hashCode methods. But this is all just syntax, the concepts remain the same as in your original code.

Generally best to strip white-space from inputs.

Add a default to your switch to catch unexpected inputs.

Here is a complete working example app with code close to your original.

package work.basil.example;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MapOut
{
    public static void main ( String[] args )
    {
        MapOut app = new MapOut();
        app.demo();
    }

    private void demo ( )
    {
        // ----------|  Data  |------------------------------------------
        record City( String name , String code )
        {
        }

        Map < String , City > map = Map.of(
                "MOW" , new City( "Moscow" , "MOW" ) ,
                "LON" , new City( "London" , "LON" ) ,
                "NYC" , new City( "New York" , "NYC" ) ,
                "BER" , new City( "Berlin" , "BER" ) ,
                "DEL" , new City( "New Delhi" , "DEL" )
        );
        System.out.println( "map = " + map );

        // ----------|  Action  |------------------------------------------
        ExecutorService executorService = null;
        try (
                Scanner scanner = new Scanner( System.in ) ;
        )
        {
            executorService = Executors.newFixedThreadPool( 5 );

            for ( String key : map.keySet() )
            {
                City city = map.get( key );
                System.out.println( "City code: " + city.code + " | name: " + city.name );
            }
            System.out.println( "Select a minimum of three and a maximum of five cities listed above. First of all, please specify the number of cities you will choose: " );
            int length = scanner.nextInt();
            System.out.println( "Please enter " + length + " city codes, pressing Return/Enter after each: " );
            List < String > inputCodes = new ArrayList <>( length );
            for ( int i = 0 ; i < length ; i++ )
            {
                String input = scanner.next();
                inputCodes.add( input.strip().trim() );
            }

            for ( String inputCode : inputCodes )
            {
                switch ( inputCode )
                {
                    case "MOW" -> executorService.submit( ( ) -> System.out.println( map.get( inputCode ).name ) );
                    case "LON" -> executorService.submit( ( ) -> System.out.println( map.get( inputCode ).name ) );
                    case "NYC" -> executorService.submit( ( ) -> System.out.println( map.get( inputCode ).name ) );
                    case "BER" -> executorService.submit( ( ) -> System.out.println( map.get( inputCode ).name ) );
                    case "DEL" -> executorService.submit( ( ) -> System.out.println( map.get( inputCode ).name ) );
                    default -> throw new IllegalStateException( "Expected city code: " + inputCode );
                }
            }
        }
        finally
        {
            if ( Objects.nonNull( executorService ) )
            {
                executorService.shutdown(); // Always shutdown your executor service. Otherwise it may continue indefinitely, like a zombie ‍.
            }
        }
    }
}

As currently written, there is no point to doing a switch on the input codes. We could drop the switch and use a single line executorService.submit( ( ) -> System.out.println( map.get( inputCode ).name ) );. But I assume you have other code-specific logic in mind, so I left that switch in place.

When run, where the user inputs: 2, MOW, and LON.

map = {MOW=City[name=Moscow, code=MOW], LON=City[name=London, code=LON], NYC=City[name=New York, code=NYC], DEL=City[name=New Delhi, code=DEL], BER=City[name=Berlin, code=BER]}
City code: MOW | name: Moscow
City code: LON | name: London
City code: NYC | name: New York
City code: DEL | name: New Delhi
City code: BER | name: Berlin
Select a minimum of three and a maximum of five cities listed above. First of all, please specify the number of cities you will choose: 
2
Please enter 2 city codes, pressing Return/Enter after each: 
MOW
LON
Moscow
London
Basil Bourque
  • 218,480
  • 72
  • 657
  • 915