【问题标题】:Java - Printing ArrayList objects in specific format through toString() methodJava - 通过 toString() 方法以特定格式打印 ArrayList 对象
【发布时间】:2019-05-12 12:34:33
【问题描述】:

我正在制作一个太阳系模型,该模型通过使用类来获取不同的太阳系和行星集。我选择使用数组列表来存储太阳系内行星的每个对象,尽管现在正在努力以合适的格式输出数据。

我在 toString() 方法中寻找的格式是“行星 X 的质量为 A 地球,BAU 来自其恒星,轨道为 C 年:可以居住吗? D'

我曾尝试使用 for 循环来打印每个行星,但不要相信这是正确的方法,因为返回会导致循环停止。非常感谢

SolarSystem.java

import java.util.ArrayList;
public class SolarSystem {

    private String systemName;
    private double systemLuminosity;


    public SolarSystem(String name, double luminosity) {
        this.systemName = name;
        this.systemLuminosity = luminosity;
    }

    ArrayList<Planet> list = new ArrayList<>();

    public void addPlanet(String name, double mass, double distance) {

        list.add(new Planet(name, mass, distance, systemLuminosity));

    }

    public void planetProperties() {

    }

    public String toString() {
        System.out.println(list.size());
        String results = "+";
        for (Planet planet : list) {
            results += planet.getName(); //if you implement toString() for Dog then it will be added here
        }
        return results;
    }
}

Planet.java

    public class Planet {

        private String planetName;
        private double planetMass;
        private double distanceFromStar;
        private double orbitalPeriod;
        private String isHabitable;

        public Planet(String name, double mass, double distance, double systemLuminosity) {

            setName(name);
            setMass(mass);
            setDistanceFromSun(distance);
            setOrbitalPeriod(distance);
            setIsHabitable(mass, distance, systemLuminosity);


        }

        public void setName(String name) {
            planetName = name;
        }

        public  String getName() {
            return planetName;
        }

        public  void setMass(double mass) {
            planetMass = mass;
        }

        public double getMass() {
            return planetMass;
        }

        public void setDistanceFromSun(double distance) {
            distanceFromStar = distance;
        }

        public double getDistanceFromStar() {
            return distanceFromStar;
        }

        public void setOrbitalPeriod(double distance) {
            orbitalPeriod = Math.sqrt(distance*distance*distance);
        }

        public double getOrbitalPeriod() {
            return orbitalPeriod;
        }

        public void setIsHabitable(double mass, double distance, double luminosity) {
            if (mass >= 0.6 && mass <= 7.0) {
                if ((distance >= 0.75 * Math.sqrt(luminosity)) && (distance <= 2.0 * Math.sqrt(luminosity))) {
                    isHabitable = "yes";
                } else {
                    isHabitable = "no";
                }
            } else {
                isHabitable = "no";
            }

        }

        public String getIsHabitable() {
            return isHabitable;
        }
    }

Main.java

public class Main {

    public static void main(String[] args) {

        //Create our solar system
        SolarSystem ourSystem = new SolarSystem("Our System",1.0);

        //Add planets in our solar system
        ourSystem.addPlanet("Mercury", 0.055, 0.387);
        ourSystem.addPlanet("Venus", 0.815, 0.723);
        ourSystem.addPlanet("Earth", 1.0, 1.0);
        ourSystem.addPlanet("Mars", 0.107, 1.52);
        ourSystem.addPlanet("Jupiter", 317.8, 5.20);
        ourSystem.addPlanet("Saturn", 95.2, 9.58);
        ourSystem.addPlanet("Uranus", 14.5, 19.20);
        ourSystem.addPlanet("Neptune", 17.1, 30.05);

        System.out.println(ourSystem.toString());



    }
}

【问题讨论】:

  • 如果你想这样显示行星的信息,你只需要在你的 Planet 类中添加一个.toString() 方法并将results += planet.getName(); 行更改为results += planet.toString();

标签: java class oop arraylist


【解决方案1】:

要呼应其他海报,首先需要在planet 类中定义一个自定义的toString() 方法。请在下面查看我的建议。它们显示为动态键入的伪代码,而不是实际代码(因为这里和那里可能有一些东西可能无法编译。)

但是伪代码应该给出一个可能的解决方案的想法。如果您仍有问题,请联系我。

根据您的要求:

我在 toString() 方法中寻找的格式是 'Planet X has 一个地球的质量,是它的恒星的 BAU,并在 C 年的轨道上运行:可以 适合居住吗? D'

您的 Planet.toString 方法可以如下所示(这是伪代码,不一定是可编译的,但您了解它的要点。)

public class Planet {

    /* your class as it is, with the 
     * addition of a possible toString 
     * implementation */

        public String toString(){
                return String.format(
                    "Planet: %s, " + 
                    "mass: %f, " + 
                    "distance: %f, " + 
                    "orbital period: %f, " + 
                    "habitable: %b" 
                    this.getName(), 
                    this.getMass(), 
                    this.getDistanceFromStar(), 
                    this.getOrbitalPeriod(),
                    this.getIsHabitable());
        }
}

然后,您的 SolarSystem 类应该有一个适当的 toString 方法,该方法循环遍历其中的行星集合。你原来的 toString 方法有正确的想法,我只是扩展了这个概念。

public class SolarSystem {

    /* 
    Your solar system class plus some changes 

    ... 
    */

    public String getName(){
        return this.systemName;
    }

    public String getLuminosity(){
        return this.systemLuminosity;
    }

    public int getPlanetCount(){
        return this.list.size();
    }

    public String toString() {
        final StringBuffer buffer = new StringBuffer();
        buffer.append(
            String.format("System: %s\nLuminosity: %f\nPlanet Count:%d\n",
                this.getName(),
                this.getLuminosity(),
                this.getPlanetCount()
            )
        );
        for (final Planet planet : list) {
            buffer.append('\t')
                .append(planet.getString())
                .append('\n');
        }
        return buffer.toString();
    }

}

现在,我有点困惑:

我曾尝试使用 for 循环来打印每个行星,但不要 相信这是正确的方法,因为返回会导致循环 停止。非常感谢

如果 return 在循环内完成,则 return 语句将停止循环。

在循环内调用的函数内完成的返回语句不会结束循环。

也就是说,return 只结束进行 return 调用的函数,而不是调用链中的函数。

比较一下

for(Foo f : fooList){
  if(something){ 
    return; // this will stop the loop
  }
}

有了这个

for(Foo f : fooList){
   if(something){
      callThisFu(); // the return within callThisFu *will not* exit the loop
   }
}

希望这能解决这个问题。

【讨论】:

    【解决方案2】:

    您必须在Planet 类中重新定义toString 并替换SolarSystemtoString 才能使用它。

    public class Planet {
      ...
      public String toString() {
         return "Planet " + planetName + " has a mass of " + planetMass + 
                " Earths, is BAU from its star, and orbits in " + orbitalPeriod + 
                " years: could be habitable? " + isHabitable;
      }
    }
    
    public class SolarSystem {
      ...
    
      public String toString() {
        String results = "";
         for (Planet planet : list) {
            results += planet.toString() + "\n"; // Use the toString of planet and add a new line 
         }
         return results;
      }
    }
    

    注意:出于性能原因,正如 oleg 所评论的,最好使用 StringBuilder 来连接字符串。在这种情况下,您的项目很少并且问题与性能无关,您可以离开 + 运算符。


    增长您的 java 知识,您会发现有用的函数,例如 String.join:

    返回一个由 CharSequence 元素的副本和指定分隔符的副本连接在一起的新字符串。

    这将帮助您维护您的代码更简单、更干净,替换它:

    public String toString() {
        String results = "";
         for (Planet planet : list) {
            results += planet.toString() + "\n"; // Use the toString of planet and add a new line 
         }
         return results;
      }
    

    public String toString() {
      return String.join("\n", list);
    }
    

    但我的建议是在尝试使用更高级的功能之前从 java 的基础开始。否则你会在不知道幕后发生什么的情况下使用它们

    【讨论】:

    • @oleg.cherednik 这是一个例子。它可以使用 StringBuilder 来完成,但它增加了可读性的复杂性,并且超出了本示例的范围
    • 无论如何,这是不好的做法,不应该这样做。这家伙可能不知道这一点并复制您的解决方案。
    • @oleg.cherednik 这对于第一次练习来说是可以的。如果你不知道 toString 是如何工作的,你就不能介绍性能方面。保持解决方案尽可能简单是一个很好的品质,可以将注意力集中在使用 toString 的示例的目标上
    【解决方案3】:

    您需要在您的Planet 类中实现一个toString() 方法,例如:

    class Planet {
        private String planetName;
        private double planetMass;
        private double distanceFromStar;
        private double orbitalPeriod;
        private String isHabitable;
    
        @Override
        public String toString() {
            return String.format(
                    "Planet %s has a mass of %f Earths, is %f from its star, and orbits in %f years: could be habitable? %s%n",
                    this.planetName, this.planetMass, this.distanceFromStar, this.orbitalPeriod, this.isHabitable);
        }
    
    }
    

    然后在您的 SolarSystem 类中,您可以创建一个类似这样的列表,您已经拥有几乎正确的部分,但我已将 getName 更改为 toString

    @Override
    public String toString() {
        StringBuilder buf = new StringBuilder();
    
        for (Planet planet : list) {
            buf.append(planet);
        }
    
        return buf.toString();
    }
    

    【讨论】:

    • planetMass 怎么样?这不是地球质量的数量
    • @RafałSokalski 输入的值是地球质量的数量source
    • @oleg.cherednik 很公平,我已经修复了它,但这是他的原始代码,但略有改动。
    【解决方案4】:

    如果你想打印出整个太阳系的描述(行星的整个数组列表),我建议在 Planet 类中实现 toString() 方法。这样做将允许您简单地遍历行星数组列表,并且只需调用 planet.toString()。将单个行星的逻辑封装在 Planet 类中是可行的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 2015-06-10
      • 2014-06-02
      • 1970-01-01
      相关资源
      最近更新 更多