当前位置: 动力学知识库 > 问答 > 编程问答 >

java - Change "perspective" of multi-dimension tree

问题描述:

|-- Car |-- Green

| |-- Audi | |-- Car

| | |-- Green | | `-- Audi

| | |-- Blue | `-- Bike

| | `-- Red | `-- BMW

| `-- BMW |-- Blue

| |-- Red | `-- Car

| `-- Yellow ==========> | `-- Audi ==========> etc.

`-- Bike |-- Red

|-- BMW | |-- Car

| |-- Yellow | | |-- Audi

| |-- Blue | | `-- BMW

| `-- Green | `-- Bike

`-- Honda | `-- Honda

|-- Red `-- Yellow

`-- Yellow |-- Car

| `-- BMW

`-- Bike

|-- BMW

`-- Honda

I want to implement several "perspectives" in a tree builder, in a generic fashion.

There are 6 possible permutations of this tree, I've just drawn 2 of them.

What I tried:

  • I'm using a generic tree structure, where every node knows its parent and children, and has a payload.
  • Classes: TreeBuilder, AbstractNode, VehicleNode, ColorNode, MakerNode, and another ordered list of enums which defines the order of the levels: BY_VEHICLE, BY_COLOR, BY_MAKER - you switch these around to get desired perspective
  • Iterate through the list of enums, collecting ALL entities specific to that enum value (cars, makers, colors) as objects or so. With a factory method, create a node using the enumValue, while passing the tree builder, and the parentEnumValue (for a top-level, the parent enum value is NULL).
  • Child has a getParentMember_Internal which fetches the corect parent based on parentEnumValue (by using the treeBuilder which contains all the data mappings)
  • In the previous iteration which I've mentioned, using the parent object of the resulting node, we can search through the tree and see which node it is (keep in mind levels are created top-down, so parents already exist)

Why it doesn't work:

  • When searching for the correct parent, there may be several instances of it in the tree, so we are forced to look at the grandparent as well.
  • Also, branches may be duplicated (see second tree)

What I'm asking:

  • Is there a specific naming for this kinda of tree/algorithm? I couldn't think of an English term for this to use in Google.
  • Does it have anything to do with a "K-D Tree"?
  • Is there a generic way to do this sort of thing?


EDIT 1 @Andreas

There are only 3 possible entities in the tree: Vehicle, Color, Maker. There is not "vehicle type". All payloads in the tree are subclasses of these three.

I call them "payloads", because each object is wrapped in a AbstractNode subclass (which is part of a tree structure) to separate the data from the presentation layer. Example: VehicleNode has a Vehicle payload.

Since the entities are independent from eachother, levels may be hidden.

This would be a valid case:

|-- Green

| |-- Audi

| `-- BMW

|-- Blue

| `-- Audi

|-- Red

| |-- Audi

| |-- BMW

| `-- Honda

`-- Yellow

|-- BMW (notice this doesn't appear twice under 'yellow', like in the second tree above)

`-- Honda

网友答案:

In SQL, this is like a Star Schema, used in Data Warehouse databases for Online Analytical Processing (OLAP).

In your case, that would be a Fact table Vehicle and 3 Dimensions (Type, Brand, Color).

I'd suggest keeping the vehicles in a list, and build the 6 trees/indexes from the list, rather than trying to convert one tree to another.

A fully typed implementation might be to define a generic abstract tree:

public abstract class Tree<F, D1, D2, D3> {
    protected Tree(List<F> facts) {
        // code here using getDimensionN() to build tree
    }
    protected abstract D1 getDimension1(F fact);
    protected abstract D2 getDimension2(F fact);
    protected abstract D3 getDimension3(F fact);
    public List<F> get(D1 dimension1) {
        // code here
    }
    public List<F> get(D1 dimension1, D2 dimension2) {
        // code here
    }
    public List<F> get(D1 dimension1, D2 dimension2, D3 dimension3) {
        // code here
    }
    // other public accessor methods here
}

You can then construct a particular tree using code like:

List<F> facts = ...;
Tree<Vehicle, Type, Brand, Color> typeBrandColorTree = new Tree<Vehicle, Type, Brand, Color>(facts) {
    protected Type getDimension1(Vehicle vehicle) { return vehicle.getType(); }
    protected Brand getDimension2(Vehicle vehicle) { return vehicle.getBrand(); }
    protected Color getDimension3(Vehicle vehicle) { return vehicle.getColor(); }
};

// Use of tree
List<Vehicle> audiCars = typeBrandColorTree.get(Type.CAR, Brand.AUDI);

Update

The Star Schema may not be appropriate for your particular question, so this is more for information about Star Schemas. Let me use an example to illustrate what a Fact might be.

A fact could be the sale of a Vehicle, where the sale statistics being tracked includes:

  • Type (Car, Bike)
  • Brand (Audi, BMW, Honda)
  • Color (Green, Blue, Red, Yellow)
  • Date
  • Price

The trees/indexes can then be used to answer questions like:

  • Show sales of Audi Cars.
  • How many Blue Bikes were sold?
  • List total sales amount by Brand.

For faster access, the tree nodes could even have pre-aggregated values like Count and TotalPrice, such that you won't need to iterate all the facts to get your answers.

This is mainly used for huge data sets (e.g. 10 years of national sales data), to help managers get various summary statistics on-demand, fast. Hence the term "Online Analytical Processing".

分享给朋友:
您可能感兴趣的文章:
随机阅读: