将信息读取到地图

时间:2014-10-20 21:57:03

标签: java eclipse set maps

我正在 Daniel Liang Java Programming Introduction 一书中学习集合和映射。我的教授在本章的后面分配了一个问题,要求我创建一个程序:

  • 查询用户输入名称
  • 查询用户的性别

使用这两个标准,以及这个/这些网站:

http://cs.armstrong.edu/liang/data/babynamesranking2001.txt 
... http://cs.armstrong.edu/liang/data/babynamesranking2010.txt

我必须能够获得排名。

我应该将此信息转换为10个地图的数组。 每张地图对应一个.txt文件/年。这是我遇到问题的地方。我该怎么做?

学生的(Int)等级是地图的值,关键是婴儿的名字(字符串)。

我的想法是创建一个地图数组或者它们的列表。所以喜欢:

List<Map<Int, String>><Map<Int, String>[] myArray;

即使在那之后如何我从.txt文件中获取所有这些信息到我的地图的问题对我来说也很难。

这是我到目前为止所提出的。我不能说我很高兴。当我尝试开始读取信息时它甚至不起作用是因为我没有指定我的数组的大小。

public class BabyNamesAndPopularity
{
    public static void main (String[] args) throws IOException
    {
      Map<Integer, String>[] arrayOfMaps;
      String myURL = "cs.armstrong.edu/liang/data/babynamesranking2001.txt";
      java.net.URL url = new java.net.URL(myURL);
      Scanner urlInput = new Scanner (url.openStream());
      while(urlInput.hasNext())
      {
        ...
      }
    }
}

制作一套MAPS是否可行?我有点认为制作一组地图会更好,因为集合会根据需要进行扩展(根据负载因子)。我只需要一些一般性指导。不幸的是,在我的大学(佛罗里达州佛罗伦萨的弗朗西斯马里恩大学)的CS课程非常小,我们没有这个东西的任何导师。

1 个答案:

答案 0 :(得分:0)

这个答案相当模糊,因为问题的广泛性,它可能更适合 programmers SE site。不过,你可能会发现这两点值得一试。

  1. 不要考虑'原始'复合集合,例如集合的映射列表等,尝试创建一组域类型,这将反映您的问题域,并且,作为下一步,使用合适的Java集合或数组实现这些类型。

  2. 单元测试和渐进式细化。不是立即开始访问远程数据(通过java.net.URL),而是从静态数据源开始。这里的想法是拥有“可靠”且易于访问的输入数据手,这将允许您轻松编写单元测试,无需访问网络甚至文件系统,使用上面第1点的域类型集。在编写单元测试时,您可以在单元测试中创建必要的域类型/方法名称,然后实现这些类型/方法,然后通过单元测试。


  3. 例如,您可以通过编写以下单元测试来启动(我假设您知道如何在IDE中组织Java项目,因此可以正确运行单元测试):

    public class SingleFileProcessingTest {
    
        private static String[] fileRawData;
    
        @BeforeClass
        public static void fillRawData() {
            fileRawData = new String[2];
            // values are from my head, resembling format from links you've posted
            fileRawData[0] = "Jacob\t20000\tEmily\t19999";
            fileRawData[1] = "Michael\t18000\tMadison\t17000";
        }
    
        @Test
        public void test() {
            Rankings rankings = new Rankings();
            rankings.process(fileRawData);
            assertEquals("Jacob", rankings.getTop().getName());
            assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
            assertEquals(18000, rankings.getScoreOf("Michael"));
            assertEquals(4, rankings.getSize());
        }
    }
    

    当然,这甚至都不会编译 - 您需要输入Rankings类的代码,getTop()getScorerOfPosition(int)返回的类代码等等。完成编译后,您需要进行测试通过。但是你在这里得到了主要的想法 - 域类型和渐进式细化。并且易于验证的代码不依赖于文件系统或网络。只是简单的旧java对象(PO​​JO)。在您正确使用POJO并进行测试(涵盖用例的大部分内容)之后,可以稍后添加使用外部数据源的代码。


    UPDATE 实际上,我在上面的代码中混淆了抽象级别:正确的Rankings类不应该处理原始数据,最好在单独的类中完成,比方说, RankingsDataParser。有了这个,重命名为RankingsProcessingTest的单元测试将是:

    public class RankingsProcessingTest {
    
        @Test
        public void test() {
            Rankings rankings = new Rankings();
    
            rankings.addScorer(new Scorer("Jacob", 20000));
            rankings.addScorer(new Scorer("Emily", 19999));
            rankings.addScorer(new Scorer("Michael", 18000));
            rankings.addScorer(new Scorer("Madison", 17000));
    
            assertEquals("Jacob", rankings.getTop().getName());
            // assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
            // implementation of getScorerOfPosition(int) left as exercise :)
            assertEquals(18000, rankings.getScoreOf("Michael"));
            assertEquals(4, rankings.getSize());
        }
    
    }
    

    随着RankingsScorer的初步实施,这实际上是编译并通过:

    class Scorer {
        private final String name;
        private final int rank;
    
        Scorer(String name, int rank) {
            this.name = name;
            this.rank = rank;
        }
    
        public String getName() {
            return name;
        }
    
        public int getRank() {
            return rank;
        }
    }
    
    class Rankings {
    
        private final HashMap<String, Scorer> scorerByName = new HashMap<>();
    
        private Scorer topScorer;
    
        public Scorer getTop() {
            return topScorer;
        }
    
        public void addScorer(Scorer scorer) {
            if (scorerByName.get(scorer.getName()) != null)
                throw new IllegalArgumentException("This version does not support duplicate names of scorers!");
            if (topScorer == null || scorer.getRank() > topScorer.getRank()) {
                topScorer = scorer;
            }
            scorerByName.put(scorer.getName(), scorer);
        }
    
        public int getSize() {
            return scorerByName.size();
        }
    
        public int getScoreOf(String scorerName) {
            return scorerByName.get(scorerName).getRank();
        }
    }
    

    用于解析原始数据的单元测试将从以下开始(如何下载原始数据应该是另一个类的责任,需要单独开发和测试):

    public class SingleFileProcessingTest {
    
        private static String[] fileRawData;
    
        @BeforeClass
        public static void fillRawData() {
            fileRawData = new String[2];
            // values are from my head
            fileRawData[0] = "Jacob\t20000\tEmily\t19999";
            fileRawData[1] = "Michael\t18000\tMadison\t17000";
        }
    
        @Test
        public void test() {
           // uncomment, make compile, make pass
    /*
            RankingsDataParser parser = new RankingsDataParser();
            parser.parse(fileRawData);
            Rankings rankings = parser.getParsedRankings();
            assertNotNull(rankings);
    */
        }
    }